介绍

本文主要解说1.8版本内存结构和回收机制,以及如何优化。

java hutools 如何得到 ClientAnchor_老年代

名词解释

1.程序计数器
记录正在执行的虚拟机字节码的地址;

2.虚拟机栈
方法执行的内存区,每个方法执行时会在虚拟机栈中创建栈帧;

3.本地方法栈
虚拟机的Native方法执行的内存区;

4.Java堆+元空间
对象分配内存的区域;

5.方法区
存放类信息、常量、静态变量、编译器编译后的代码等数据;常量池:存放编译器生成的各种字面量和符号引用,是方法区的一部分。

Java Client和Server JVM区别

Java HotSpot Server VM:用于运行服务器应用程序,更喜欢最大化运行速度,而不是最小化启动时间.
Java HotSpot Client VM:更适合GUI应用程序,旨在提供快速启动时间或小占地面积.

HotSpot

快速的内存分配和垃圾收集-Java HotSpot技术可为对象提供快速的内存分配,并且提供了快速,高效,最新的垃圾收集器的选择。

总堆

java hutools 如何得到 ClientAnchor_Java_02

jdk1.8以前Java将堆内存分为3大部分,分别为年轻代、老年代、永久代,在之后永久代取消了,由元空间取代。

您可以使用标志-Xms(初始堆大小)和-Xmx(最大堆大小)来指定初始堆大小和最大堆大小。

如果你知道你的应用程序有多少堆需要工作做好,你可以设置-Xms和-Xmx相同的值。

否则,JVM将使用初始堆大小开始,或者默认本机内存的4分之1大小,然后将增大Java堆,直到找到堆使用和性能之间的平衡为止。

年轻代

年轻代分为Eden、S0、S1,S代表Survivor。它的大小将根据总堆的最大的大小和NewRatio参数值来计算,例如,设置-XX:NewRatio=3意味着年轻一代和终身一代之间的比率为1:3。换句话说,Eden空间和Survivor空间的总大小将是堆总大小的四分之一,Oracle也推荐使用此比例。

参数

服务器JVM默认值

描述

NewRatio

2

年轻代相对于总堆大小的比例

NewSize

1310M

设置年轻代的初始大小

MaxNewSize

不限

设置年轻代的最大大小

SurvivorRatio

8

设置eden空间和survivor空间比例,默认8代表Eden空间占80%,剩下S0和S1各占10%

Eden & Survivor

介绍

为了减少送到老年代的对象,进而减少Full GC的发生,Survivor的预筛选保证,只有经历16次Minor GC还能在新生代中存活的对象,才会被送到老年代。

新建的对象在Eden中,经历一次Minor GC,Eden被清空,其存活对象就会被移动到第一块survivor space S0;

等Eden区再满了,就再触发一次Minor GC,Eden和S0中的存活对象又会被复制送入第二块survivor space S1(这个过程非常重要,因为这种复制算法保证了S1中来自S0和Eden两部分的存活对象占用连续的内存空间,避免了碎片化的发生)。

S0和Eden被清空,然后下一轮S0与S1交换角色,如此循环往复。如果对象的复制次数达到16次,该对象就会被送到老年代中( 默认是 15 岁,可以通过参数 -XX:MaxTenuringThreshold 来设定 )。

整个过程中,永远有一个survivor space是空的,另一个非空的survivor space无碎片。

使用

参数SurvivorRatio来调整幸存空间的大小,但这对于性能通常并不重要。例如,-XX:SurvivorRatio=6将Eden和Survivor空间之间的比例设置为1:6。换句话说,每个幸存者空间将是伊甸园大小的六分之一,因此是年轻一代的八分之一(而不是七分之一,因为有两个幸存者空间)。

如果幸存者空间太小,则复制集合将直接溢出到终身代。如果幸存者空间太大,它们将毫无用处.

老年代

老年代中存放的对象年龄大于15的对象。在老年代触发的gc叫major gc也叫full gc。

full gc会包含年轻代的gc。full gc采用的是标记-清除算法。会产生内存碎片。

在执行full gc的情况下,会阻塞程序的正常运行。老年代的gc比年轻代的gc效率上慢10倍以上。对效率有很大的影响。

元空间

元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过以下参数来指定元空间的大小:

-XX:MetaspaceSize = ,其中是初始化的Metaspace大小,控制元空间发生GC的阈值。GC后,动态增加或降低MetaspaceSize。在默认情况下,这个值大小根据不同的平台在12M到20M浮动。使用Java -XX:+PrintFlagsInitial命令查看本机的初始化参数

-XX:MaxMetaspaceSize = size,设置可以分配给类元数据的本机最大内存,当然也要考虑其他正在运行的应用程序以及系统上可用的内存量。默认情况下,大小不受限制。

-XX:MinMetaspaceFreeRatio = ,其中是在GC之后释放类元数据容量的最小百分比,以避免分配给类元数据的空间量(高水位标记)增加,这将导致垃圾回收。

-XX:MaxMetaspaceFreeRatio = ,其中是在GC之后可用的类元数据可用容量的最大百分比,以避免减少分配给类元数据的空间(高水位标记),这将导致垃圾回收。

-XX:MaxHeapFreeRatio=percent,设置在GC回收后最大可被允许的堆空间(0 to 100).如果空闲的堆空间在这个值之上将收缩 .默认值是70%.

MaxMetaspaceExpansionMetaspace增长时的最大幅度。

MinMetaspaceExpansionMetaspace增长时的最小幅度。

查看默认配置

widnwos
java -XX:+PrintFlagsFinal -version |findstr “MinHeapFreeRatio”

linux
java -XX:+ PrintFlagsFinal <GC选项> -version| grep MaxHeapSize

jmap -heap pid
可以查看内存的使用情况

回收机制

-XX:ParallelGCThreads=number:设置年轻一代和老一代中用于并行垃圾回收的线程数。缺省值取决于JVM可用的CPU数量。

-XX:+UseSerialGC:设置串行收集器

-XX:+UseParallelGC:设置并行收集器

-XX:+UseParalledlOldGC:设置并行年老代收集器

-XX:+UseConcMarkSweepGC:设置并发收集器

优化配置

Java启动参数共分为三类

1.标准参数(-),所有的JVM实现都必须实现这些参数的功能,而且向后兼容;

2.非标准参数(-X),默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足,且不保证向后兼容;

3.非Stable参数(-XX),此类参数各个jvm实现会有所不同,将来可能会随时取消,需要慎重使用;