JVM运行时内存区是如何划分的?
方法区(Method Area):存储类的字节码信息、常量池
堆区(Heap Area):存储对象
Java方法栈(Stack Area):所有方法运行时,会创建一个栈帧对象,然后进入栈(方法栈)
本地方法栈(Native Method Stack Area):用C语言写的,方法执行时候,会进入本地方法栈
程序计数器(Pc Register):用于记录当前线程要执行的下一条字节码指定的地址
如何理解方法区(Method Area)?
方法区是逻辑一种定义,是一种规范,可被所有线程共享,不同JVM对方法区的落地实现可能不同,例如在JDK7中方法区称之为持久代,在JDK8中方法区叫元空间(Metaspace),并且这个元空间可以是JVM堆外的一块内存,不占用操作系统为JVM分配的内存。
如何理解JAVA中的堆(Heap),他的构成是怎样的?
Java中的堆是用于存储对象的一块区域,可被所有线程所共享。这块区域又可以分为年轻代和老年代,年轻代又分为伊甸园区和2个幸存区(有一块区域始终是空的)。
JVM虚拟机栈的结构是怎样的?
Java中每个线程都有一个虚拟机栈(Java方法栈)每个方法的执行都会对应着一次入栈(Push)和出栈(Pop)操作,栈中的元素为一个一个的栈帧(Stack Frame)对象,这个栈帧的构成主要有如下几部分:
1、操作数栈(用于执行运算)
2、局部变量表(用于存储方法内部的局部变量)
3、方法的返回值(存储方法的返回值)
4、动态链接(方法中要访问的一些常用池数据,要调用的方法,都会对应一个链接)
5、其他信息
如何理解程序计数器?
程序计数器用于记录当前线程要执行的下一条指令的偏移量地址,每个线程都有一个程序计数器,这个程序计数器也是所有内存中唯一一个不会出现内存溢出的区域
Java对象分配内存的一个基本过程是怎样的?
1、编译器通过逃逸分析(JDK8已默认开启)判定对象是在堆上分配还是在栈上分配
2、假如确定是在堆上分析,则可首先选择TLAB区,检测这块区域是否可以存储这个对象,可以则存储
3、假如TLAB区无法存储新创建的对象,则可以考虑在TLAB区之外的Eden区加锁分配(这里为什么加锁分配:申请分配内存的时候,有可能在java堆的同一个位置申请,这时就需要对拟分配的内存区域进行加锁或者采用CAS等操作,保证这个区域只能分配给一个线程)
4、如果Eden区无法存储对象,则执行Young GC(Minor)-年轻代的垃圾回收
5、假如Eden区执行了Young GC之后,仍然不足以存储对象,则直接分配到老年代。
6、假如老年代也不足以存储这个对象,则执行Full GC,这个过后还不能存储对象则抛出异常。
JVM中年轻代中幸存区设置的比例比较小,可能会产生什么问题?
年轻代的伊甸园区对象越来越多时,会启动Young GC,此时伊甸园区的对象就要拷贝到幸存区。假如这个幸存区比较小,无法存储从伊甸园区拷贝过来的幸存对象,此时这些对象就直接分配到老年代,就会导致老年代的对象越来越多,触发老年代GC的频率就变高,老年代的GC一般为Full GC,这个GC的时间会比较长,会影响系统的吞吐量和执行效率。说明:伊甸园区与两个幸存区的比例通常是8:1:1
假如伊甸园区设置的比例比较小,可能会出现什么问题?
我们创建的对象,大部分都是存储在伊甸园区。假如伊甸园区设置的比例小了,可能会增加GC频率。GC时,用户线程会出现短时间的暂停,这样会影响系统的执行性能。
JVM的堆内存为什么要分为年轻代和老年代?
通过分代设计,减少GC的空间范围,提高GC效率。
JVM调优中为什么推荐初始堆大小和最大堆大小要设置成一样的(-Xms2048m -Xms2048m)?
避免程序在运行过程中,因对象的多少或GC后内存的变化,进而导致的内存大小的调整,这个内存大小的调整的过程可能会带来更大的系统开销。(阿里的开发规范中)
标签:存储,对象,GC,内存,JVM,线程,运行 From: https://www.cnblogs.com/yangcrazy/p/17124632.html