页面加载中...

JVM内存模型

| Java | 0 条评论 | 817浏览

内存模型

Java的内存是自动内存管理机制,不像c++那样程序员拥有内存管理的最高权限。JVM在执行Java程序时会把它所管理的内存划分成若干个不同的数据区域。内存模型如下

这些区域都有各自的用途,有的区域随虚拟机启动而存在,有些区域则时依赖用户线程的启动结束而建立销毁。Java的运行时数据区主要由以下几部分组成:

方法区

当一个Class文件被类加载器加载到了内存中,该类的一些基本信息:对象类型、父类、实现的接口、方法、静态变量等等都是存放在该区域中。也就是说,方法区是存放类的公用信息的的地方。

一般来讲,放置在该区域的数据就不会轻易被垃圾回收,除非某个类被卸载。所以,在gc中,该区域可认为是永久代。

其中,常量是放在运行时常量池的。

运行时常量池

该区域时方法区的一部分,主要存放编译期间生成的各种字面和符号引用。

字面常量就是一些常数,如:字符串,final标识的常量

符号引用就是该Class文件的一些描述,如该类的全限定名。

这里面的常量不一定都是在编译期间生成的,也可以在程序运行中动态地生成常量,如通过使用String类的intern方法可以将某个字符串放入常量池中。

程序计数器

程序计数器(PC)是一小块内存区,存放着程序下一次操作的地址。可将其看作一个指针,总是指向程序当前正在执行那一行的下一行,程序的分支、循环、异常捕获等功能都得需要依赖PC完成。

该区域是线程私有的。

虚拟机栈

方法被执行时会在虚拟机栈同时中创建一个栈帧(stack frame),用于存放局部变量表、操作数栈、方法出口等。每一个方法从调用开始到结束的过程,就对应着一个栈帧从栈中从入栈到出栈的过程。 栈帧时方法运行期的基础数据结构。

局部变量表存放了编译期可知的各种基本数据类型,如:int,long,byte,boolean等基本数据类型,所以,在方法中,使用基本数据类型比使用包装类型更高效的。

该区域也是线程私有。

本地方法栈

本地方法栈是类似虚拟机栈的,只不过本地方法栈专门为本地方法(native标识的方法)服务的。

该区域同样也是线程私有的。

堆是JMM最重要的部分,该区域就是存储对象实例的地方。每当我们通过一个new关键字实例化一个对象时,如Object obj = new Object()。obj这个对象,即new Object() 就存放在堆中;在栈中拥有一个obj这个对象的引用。

该区域也是垃圾回收的主要区域,关于对象占用空间的大小。

如,某个类定义如下:

class Demo {
    int a;
    byte b;
    Object c;
}

当new了该类后,该对象在内存中的大小为:空对象大小(8字节)+ int类型大小(4字节)+byte类型大小(1字节)+空对象引用大小(4字节)=17字节,又因为内存的地址是每8字节连续的,所以需要的内存至少为8的证数倍,即该对象在堆中需要24个字节大小的空间。

参考

《深入理解Java虚拟机》:https://gitee.com/abreaking/learn-note/blob/master/基础书籍/深入java虚拟机.pdf

发表评论

最新评论

    来第一个评论吧!