JVM内存模型
一. JVM内存结构图(JDK1.6)
pc(程序计数器):保存当前线程正在执行的字节码的行号,线程私有;
JVM栈:栈里面存放着方法的基本数据类型和对象的引用,线程私有;
局部变量表:方法中定义的局部变量都会存放在局部变量表。
操作数栈:操作数栈将变量之间的运算入栈,存储计算结果,再出栈赋值给局部变量表
方法出口:方法出口记录了test()方法执行完成后的一个出口,也就是回到main()。
本地方法栈:本地方法供java直接调用本地 C/C++ 库方法,线程私有;
堆:存放new出来的对象和数组,是垃圾回收区域,线程共有;
方法区:用于存储被虚拟机加载的类信息、常量和static变量,线程共有。
二. JVM 内存模型(JDK1.7)
永久代仍存在于JDK1.7中,并没完全移除,譬如符号引用(Symbols)转移到了native(本地) heap;字面量(interned strings)+类的静态变量(class statics)转移到了java heap,类的加载信息还在永久代中。
三. JVM内存结构图(JDK1.8)
因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过以下参数来指定元空间的大小。
JDK8中JVM不再有方法区,方法区存储的信息:1、类信息->元数据区 2 、static变量+常量池->jvm堆中。元数据空间不在jvm中,而是使用本地内存(jvm之外的内存,但也有可能被java使用)。
为什么要移除永久代?
答案一
1、由于Permanent Generation内存经常不够用或发生内存泄露,引发恼人的java.lang.OutOfMemoryError: PermGen 。
2、移除Permanent Generation可以促进HotSpot JVM与JRockit VM(甲骨文的虚拟机)的融合,因为JRockit没有永久代。
3、对永久代进行调优是很困难的。
答案二
1、字符串存在永久代中,容易出现性能问题和内存溢出。
2、类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。
3、永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。
4、Oracle 可能会将HotSpot 与 JRockit 合二为一。
JVM使用的内存可以总体划分为两部分:Heap Memory
和Native Memory
。前者我们比较熟悉,是供Java应用程序使用的;后者也称为C-Heap,是供JVM自身进程使用的。