美文网首页
Java 内存基础知识

Java 内存基础知识

作者: Parallel_Lines | 来源:发表于2020-05-08 19:59 被阅读0次

主要介绍 Java 内存相关的基础知识,为 LeakCanary 原理分析做准备。

JVM 内存结构

JVM 在运行时内存区分为不同的区域,每个区域承担着不同的功能。

线程共享区域

1. 方法区

存放类信息(class)、常量、静态变量、JIT 编译器编译后的代码等数据。

存放常量值

2. JVM 堆

存放对象实例和数组,GC 回收的主要区域。

堆区不存放基本类型和对象引用,只存放对象本身。

存放对象实例

线程私有区域

3. 程序计数器

主要代表当前线程所执行的字节码行号指示器。

字节码解释器工作时,通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。

线程字节码行号指示器

4. JVM 栈

与线程同时创建,代表 java 方法执行的内存模型。

每个方法执行时都会创建一个 栈桢 来存储方法的的局部变量表、操作数栈、运行时常量池的引用、返回值、返回地址等信息。

每个方法从调用到结束对应一个 栈桢JVM 栈 中的入栈和出栈过程。

存放局部变量

5. Native 栈

Native 方法有关。

native

实例

说一堆概念不理解没用,看个简单的例子:

private static int key = 0; // 0

public static void main(String args[]){ 
    int a = 3; // 1
    Bean bean = new Bean(4); // 2
}

class Bean {
    private int num;

    public Bean(int n) {
        this.num = n;
    }
}

注释 0 处,值在方法区。

引用呢?求解...

注释 1 处,int a = 3,基础数据类型,引用和值都存放在 JVM 栈中,方法执行完毕将从栈中消失。

注释 2 处,Bean bean = new Bean(4),其中 :

  1. bean 为对象引用,存放在栈中,对象则存放在堆中;
  2. n = 4,n 为局部变量,存放在栈中。基础数据类型,所以值也存在栈中。当 Bean 构造函数执行完毕,n 将从栈中消失;
  3. num = 4,num 为成员变量,由于 bean 对象存放堆中,所以它的 引用和值都存放在堆里

方法执行完毕后,a 的引用和值、bean 引用将从栈中消失,bean 对象则等待 GC 回收。

jdk 1.8 后有所变化,暂不讨论;另外 String 创建对象的问题可以参考 此文章

Java 内存模型

Java 内存模型是 Java 层对内存的抽象,目的是解决多线程共享内存情况下的原子性、可见性和有序性问题。

Java 内存模型规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存中保存的是变量的主内存副本,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存。不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量的传递均需要自己的工作内存和主存之间进行数据同步进行。

volatile、synchronized、final、concurren 包等就是 Java 内存模型底层封装后提供给程序员的关键字。

关于原子性、内存可见性、有序性,可以参考 另一篇博客

引用分类

强、软(SoftReference)、弱(WeakReference)、虚(PhantomReference,ReferenceQueue)四种引用。

强引用

被强引用的对象永远不会被垃圾回收,内存不足时 OOM。

软引用

内存不足时才进行垃圾回收的引用方式。

可以用作缓存。

弱引用

只要 GC 就回收的引用方式。

可以用于子线程引用 context、handler 回调、缓存等场景。

如网络回调成功后引用 context 执行刷新页面等操作,如果网络回调时间过长,页面关闭,context 被工作线程持有则导致内存泄漏。此时使用弱引用包装 context,则 context 会在页面关闭、GC 触发时及时回收。
其它例子可以参考 知乎 上关于 ThreadLocal 中使用弱引用的描述,也很形象。
形象的说:
弱引用的对象尚在(尚有强、软引用)则用、不在则忽略,不限制对象本身的"去留"。
而软引用仅仅在内存不足时才肯放对象"离去"。

虚引用

这个引用可以在对象被收集器回收时收到一个系统通知。

当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中,所以通过检查该队列里面的内容就知道一个对象是不是已经可以被回收了。

[TOC]

相关文章

  • Android内存泄漏

    文章包括两部分: (1)java内存泄漏基础知识 (2)Android内存泄漏。 一.Java内存泄漏基础知识 1...

  • Java基础(3)——JVM内存模型

    Java for android 基础知识。 JVM的内存结构分为: 方法区(method) 栈内存(stack)...

  • Android面试题4

    1 Java基础知识。线程,java虚拟机,内存模型等。2 Android基础知识。官方API,常用控件源码,自定...

  • java开发两年,类加载器及其加载过程都搞不明白,那你工作可能不

    内存结构概述 内存结构简图: 内存结构详细图: 中文: 英文: Java基础知识大全[https://jq.qq....

  • Java 内存基础知识

    主要介绍 Java 内存相关的基础知识,为 LeakCanary 原理分析做准备。 JVM 内存结构 JVM 在运...

  • 内存泄漏

    一、java内存泄漏基础知识 1.java内存的分配策略 (1)静态存储区 方法区 (2)栈区 (3)堆区 ne...

  • 内存泄漏 快速过一下

    java 内存泄漏 基础知识 java 内存的分配策略 静态分配, 栈式分配,堆式分配对应的 静态存储区,也叫方法...

  • 原:进阶

    1.java基础知识 2.设计模式 3.内存分析 Android内存分析内存分析 4.性能优化 Android性能...

  • 内存泄漏

    java内存泄漏基础知识该被释放的时候没被释放,一直被某个对象所持有,导致不能gc。 1、java内存的分配策略1...

  • 内存泄漏

    一.java内存泄漏基础知识 1.java内存的分配策略 1)静态存储区 2)栈区:方法中的基本类型变量,对象的引...

网友评论

      本文标题:Java 内存基础知识

      本文链接:https://www.haomeiwen.com/subject/urpqnhtx.html