首页 > 系统相关 >JVM运行时内存区

JVM运行时内存区

时间:2023-02-15 20:55:12浏览次数:60  
标签:存储 对象 GC 内存 JVM 线程 运行

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

相关文章