jvm虚拟机内存区域

jvm虚拟机内存区域

JVM虚拟机区域总体分两类,heap区非heap区。即堆内存和非堆内存区域

heap区

Eden Space(伊甸园)
Survivor Space(幸存者区)
Old Gen(老年代)。

Eden Space
字面意思是伊甸园,对象被创建的时候首先放到这个区域,进行垃圾回收后,不能被回收的对象被放入到空的survivor区域。

Survivor Space
幸存者区,用于保存在eden space内存区域中经过垃圾回收后没有被回收的对象。Survivor有两个,分别为To Survivor、 From Survivor,这个两个区域的空间大小是一样的。执行垃圾回收的时候Eden区域不能被回收的对象被放入到空的survivor(也就是To Survivor,同时Eden区域的内存会在垃圾回收的过程中全部释放),另一个survivor(即From Survivor)里不能被回收的对象也会被放入这个survivor(即To Survivor),然后To Survivor 和 From Survivor的标记会互换,始终保证一个survivor是空的。

Eden SpaceSurvivor Space都属于新生代,新生代中执行的垃圾回收被称之为Minor GC(因为是对新生代进行垃圾回收,所以又被称为Young GC),每一次Young GC后留下来的对象age加1。

Old Gen
老年代,用于存放新生代中经过多次垃圾回收仍然存活的对象,也有可能是新生代分配不了内存的大对象会直接进入老年代。经过多次垃圾回收都没有被回收的对象,这些对象的年代已经足够old了,就会放入到老年代。

当老年代被放满的之后,虚拟机会进行垃圾回收,称之为Major GC。由于Major GC除并发GC外均需对整个堆进行扫描和回收,因此又称为Full GC。

heap区即堆内存,整个堆大小=年轻代大小 + 老年代大小。堆内存默认为物理内存的1/64(<1GB);默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制,可以通过MinHeapFreeRatio参数进行调整;

XX:MinHeapFreeRatio= 指定 jvm heap 在使用率小于 n 的情况下 ,heap 进行收缩 ,Xmx==Xms 的情况下无效 , 如:-XX:MinHeapFreeRatio=30

默认空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制,可以通过MaxHeapFreeRatio参数进行调整。

-XX:MaxHeapFreeRatio=
指定 jvm heap 在使用率大于 n 的情况下 ,heap 进行扩张 ,Xmx==Xms 的情况下无效 , 如:-XX:MaxHeapFreeRatio=80

下面我们用java代码来看一下最设置最大堆内存以后如何查看其分布
第一步这只最大最小堆内存为10m,最小堆内存也是10m等于没说存粹是为了测试使用

-Xmx10m -Xms10m

maxHeapMemory = Eden+Survivor+Old Gen (最大的堆内存=伊甸园区域+幸存者区+老年代区域)

/*获取最大的堆内存*/
long maxHeapMemory = Runtime.getRuntime().maxMemory() 

   for (MemoryPoolMXBean mp : ManagementFactory.getMemoryPoolMXBeans()) {
            //虚拟机区域名称 如PS Survivor Space
            String psName = mp.getName();

            //虚拟机区域类型 如Heap memory、 Non-heap memory
            String psType =  mp.getType().toString();
            
            //当前类型的区域设置的最大内存空间
            long maxMemory = mp.getUsage().getMax();
            String memory = String.format("%d (%.2f M)", s, (double) s / (1024 * 1024)); 
            System.out.println("psName:"+psName+"psType:"+psType+memory);
        }

非heap区

非heap区又分:

Code Cache(代码缓存区);
Perm Gen(永久代);
Jvm Stack(jvm虚拟机栈);
Local Method Statc(本地方法栈);

Code Cache
代码缓存区,它主要用于存放JIT所编译的代码。CodeCache代码缓冲区的大小在client模式下默认最大是32m,在server模式下默认是48m,这个值也是可以设置的,它所对应的JVM参数为ReservedCodeCacheSize 和 InitialCodeCacheSize,可以通过如下的方式来为Java程序设置。

-XX:ReservedCodeCacheSize=128m

CodeCache缓存区是可能被充满的,当CodeCache满时,后台会收到CodeCache is full的警告信息,如下所示:

“CompilerThread0” java.lang.OutOfMemoryError: requested 2854248 bytes for Chunk::new. Out of swap space?

注:JIT编译器是在程序运行期间,将Java字节码编译成平台相关的二进制代码。正因为此编译行为发生在程序运行期间,所以该编译器被称为Just-In-Time编译器。

Perm Gen
全称是Permanent Generation space,是指内存的永久保存区域,因而称之为永久代。这个内存区域用于存放Class和Meta的信息,Class在被 Load的时候被放入这个区域。因为Perm里存储的东西永远不会被JVM垃圾回收的,所以如果你的应用程序LOAD很多CLASS的话,就很可能出现PermGen space错误。默认大小为物理内存的1/64。

可以使用XX:PermSize-XX:MaxPermSize来指定最小值和最大值

Jvm Stack
虚拟机栈是用于描述java方法执行的内存模型。
每个java方法在执行时,会创建一个“栈帧(stack frame)”,栈帧的结构分为“局部变量表、操作数栈、动态链接、方法出口”几个部分(具体的作用会在字节码执行引擎章节中讲到,这里只需要了解栈帧是一个方法执行时所需要数据的结构)。我们常说的“堆内存、栈内存”中的“栈内存”指的便是虚拟机栈,确切地说,指的是虚拟机栈的栈帧中的局部变量表,因为这里存放了一个方法的所有局部变量。
  
方法调用时,创建栈帧,并压入虚拟机栈;方法执行完毕,栈帧出栈并被销毁
虚拟机栈是线程隔离的,每个线程都有自己独立的虚拟机栈。
jvm虚拟机内存区域
Local Method Statc
常用的是native 修饰符修饰的方法的功能区域
本地方法栈的功能和特点类似于虚拟机栈,均具有线程隔离的特点以及都能抛出*Error和OutOfMemoryError异常。

不同的是,本地方法栈服务的对象是JVM执行的native方法,而虚拟机栈服务的是JVM执行的java方法。如何去服务native方法?native方法使用什么语言实现?怎么组织像栈帧这种为了服务方法的数据结构?虚拟机规范并未给出强制规定,因此不同的虚拟机实可以进行*实现,我们常用的HotSpot虚拟机选择合并了虚拟机栈和本地方法栈。

备注

本文涉及到的一些jvm虚拟机设置注解

-Xmx<n>
指定 jvm 的最大 heap 大小 , 如 :-Xmx=4g 这只最大堆内存为100m

-Xms<n>
指定 jvm 的最小 heap 大小 , 如 :-Xms=4g
高并发场景 建议和-Xmx一样, 防止因为内存收缩/突然增大带来的性能影响。

-Xmn<n>
指定 jvm 中 New Generation 的大小 , 如 :-Xmn256m。 这个参数很影响性能, 如果你的程序需要比较多的临时内存,建议设置到512M, 如果用的少, 尽量降低这个数值, 一般来说128/256足以使用了。

-XX:PermSize=<n>
指定 jvm 中 Perm Generation 的最小值 , 如 :-XX:PermSize=32m。 这个参数需要看你的实际情况,。可以通过jmap 命令看看到底需要多少。

-XX:MaxPermSize=<n>
指定 Perm Generation 的最大值 , 如 :-XX:MaxPermSize=64m

-Xss<n>
指定线程桟大小 , 如 :-Xss128k, 一般来说,webx框架下的应用需要256K。 如果你的程序有大规模的递归行为,请考虑设置到512K/1M。 这个需要全面的测试才能知道。 不过,256K已经很大了。 这个参数对性能的影响比较大的。

-XX:NewRatio=<n>
指定 jvm 中 Old Generation heap size 与 New Generation 的比例 , 在使用 CMS GC 的情况下此参数失效 , 如 :-XX:NewRatio=2

-XX:SurvivorRatio=<n>
指 定 New Generation 中 Eden Space 与一个 Survivor Space 的 heap size 比例 ,-XX:SurvivorRatio=8, 那么在总共 New Generation 为 10m 的情况下 ,Eden Space 为 8m

-XX:MinHeapFreeRatio=<n>
指定 jvm heap 在使用率小于 n 的情况下 ,heap 进行收缩 ,Xmx==Xms 的情况下无效 , 如 :-XX:MinHeapFreeRatio=30

-XX:MaxHeapFreeRatio=<n>
指定 jvm heap 在使用率大于 n 的情况下 ,heap 进行扩张 ,Xmx==Xms 的情况下无效 , 如 :-XX:MaxHeapFreeRatio=70