JAVA内存模型

原创
06/17 15:25
阅读数 123

JAVA内存模型

线程角度

程序计数器(Program Counter Register)

当前程序所执行的字节码行号指示器(逻辑)

改变计数器的值来选取下一条需要执行的字节码指令

和线程是一对一的关系即“线程私有”,一个明确的时间点,处理器只会执行一个线程的代码,就需要其他线程存储自己的程序计数器,以便处理器在切换线程的时候,可以继续执行上次未执行完的逻辑。

对java方法计数,如果正在执行的方法是native方法则计数器值为undefined

因为只是记录行号,程序计数器不必担心内存泄漏的问题

JAVA虚拟机栈(Stack)

 JAVA方法执行的内存模型

包含多个栈帧

局部变量表和操作数栈

局部变量表:包含方法执行过程中的所有变量

操作数栈:入栈、出栈、复制、交换、产生消费变量。栈模型,先进后出,当方法中调用其他方法,那么也是后调用的方法先执行完,才会执行外层的方法,这就符合了栈模型。

递归为什么会引发java.lang.StackOverflowError异常?

虚拟机栈过多会引发java.lang.OutOfMemoryError异常

本地方法栈

与虚拟机相似,主要作用于标准了native的方法。

元空间(MetaSpace)与永久代(PermGen)的区别

元空间直接使用本地内存,而永久代使用JVM内存。好处:本地内存剩余多少,元空间就有多大,元空间的数据不再占用JVM内存。也不会放任元空间无限大,JVM在启动的时候会去设置元空间内存大小。

元空间相比永久代的优势

字符串常量池存在于永久代中,容易出现性能问题和内存溢出。

类和方法的信息大小难以确定,给永久代的内存大小指定带来困难,太小容易出现永久代内存溢出,太大导致内存浪费

永久代会给GC带来不必要的复杂性

方便hotSpot与其他JVM如jrockit集成

JAVA堆(Heap)

对象实例的分配区域

 

JVM三大性能调优参数-Xms -Xmx -Xss的含义

java -Xms128m -Xmx128m -Xss256k -jar xxxx.jar

-Xss:规定了每个线程虚拟栈(堆栈)的大小,此配置将会影响此JVM中线程并发数的大小

-Xms:堆的初始容量大小,一旦对象容量超过堆的初始容量,堆将会扩容

-Xmx:堆扩容后的大小,能达到的最大值

在很多情况下,我们通常将-Xms和-Xmx设置成一样的,因为当堆不够用进行扩容时,会发生内存抖动,影响程序的稳定性。

JAVA内存模型中内存分配策略

静态存储:编译时确定每个存储目标在运行时的存储空间需求。要求程序代码中,不允许有可变数据结构的存在,也不允许有嵌套和递归的结构出现,以为它们都会导致程序在编译时无法确定空间的存在。

栈式存储:数据区需求在编译时未知,运行时模块入口前确定。在进入一个程序模块的时候,必须知道进入该模块的数据区大小,才能分配其内存。

堆式存储:编译时或运行时模块入口都无法确定,动态分配。 

JAVA内存模型中堆和栈的区别

栈和堆的联系:引用对象、数组时,栈里定义的变量实际上保存的是数据在堆中的地址,就可以使用栈中的引用变量,来访问堆中的数据。堆中的数据在没有被任何栈中变量引用的时候,才可能随后被GC回收释放掉。

管理方式:栈自动释放,堆需要GC

空进大小:栈空间比较小,堆空间一般都比较大,因为要存储JAVA对象数据

碎片相关:栈产生的碎片远小于堆

分配方式:栈支持静态分配和动态分配,而堆仅支持动态分配,静态分配是本身由编译器分配好了,动态分配可能根据情况有所不同。而堆空间只能动态。

效率:栈的效率比堆高,因为栈的释放JVM就可以控制,而堆需要靠GC,GC又不是实时的。

 

 

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部