jvm优化总结 -- 理论

JVM内存组成部分:

  • 线程共享的: 方法区+堆
  • 线程独享: PC寄存器+栈+本地方法栈

具体:

  • 栈:基本数据类型数据
  • 堆:存储对象或者数组;
  • 方法区:(记忆:类型信息+类变量+方法信息+常量池)

1、类型信息,例如类的全限定名、类型的修饰符

2、常量池: 字面量(类名,成员变量名等等))、符号引用(?)

3、方法信息,例如方法名、方法的返回类型、方法参数的类型,方法的修饰符

4、类变量

 

java编辑器:

Java程序从源文件创建到程序运行要经过两大步骤:

  • 源文件由编译器编译成字节码(ByteCode)  
  • 字节码由java虚拟机解释运行。

因为java程序既要编译同时也要经过JVM的解释运行,所以说Java被称为半解释语言

 编译后的字节码文件格式主要分为两部分:常量池和方法字节码。

 

 

 

堆内存:

jvm优化总结 -- 理论

共享内存:堆 + 方法区

堆:新生代 + 老年代

新生代: 伊甸园区 + 幸存区S0 + 幸存区S1

 

新生代:

  • S0和S1空间相同 ;
  • 相关算法:coping算法来分配内存和垃圾回收  youngGC 或 minorGC
  • Eden区的对象量达到阈值后,发生一次新生代GC
  • 通过-Xmn设置新生代的大小,通过-XX:SurvivorRatio 设置Eden区和Survivor区的比值,有些垃圾回收器会对S0或者S1进行动态的调整。

老年代:

  • 在新生代中经过多次垃圾回收后仍然存活的对象,会存放在老生代 ;
  • 老生代通过 mark算法 来清理无用内存 ; fullGC 或 majorGC
  • 当年老代满时会引发Full GC,Full GC将会同时回收年轻代、年老代
  • 当永久代满时也会引发Full GC,会导致Class、Method元信息的卸载

 

永久代:

  • GC不会再主程序运行期间对 永久代进行清理,如果你的程序加载了很多class的话,请就能出现PermGen space错误 

新生代的coping算法:

jvm优化总结 -- 理论

使用3个分区进行处理,默认比例是:Eden/S0/S1 为 8:1:1,可分配新生对象的内存是总内存的90%+ 

算法过程:

1. Eden+S0可分配新生对象;

2. 对Eden+S0进行垃圾收集,存活对象复制到S1。清理Eden+S0。一次新生代GC结束

(Eden区的对象量达到阈值后,发生一次新生代GC)

3. Eden+S1可分配新生对象;

4. 对Eden+S1进行垃圾收集,存活对象复制到S0。清理Eden+S1。二次新生代GC结束。

5. 循环1。

 

 

老生代的mark算法:

标记清除算法

1、将认定为可回收的内存做一个标记

2、统一将被标记的清理

缺点:内存空间碎片化

 

jvm优化总结 -- 理论

标记-紧凑算法

在标记-清除算法的基础上,增加了碎片整理这一步,如下图:

1、标记:标记可回收的对象和存活的对象

2、紧凑:将所有存活对象向内存开始部分移动

3、清理被标记为可回收的对象

 

jvm优化总结 -- 理论

 

java垃圾回收方式--垃圾回收器:

应用:

启动时遇到StackOverflowError导致失败的解决办法

在catalina.sh的第二行添加:  CATALINA_OPTS="$CATALINA_OPTS -server  -Xss100m  -XX:+UseG1GC"

 

串行垃圾回收器:

它为单线程环境设计,只使用一个单独的线程进行垃圾回收,通过冻结所有应用程序线程进行工作,所以可能不适合服务器环境。

它最适合的是简单的命令行程序。 

通过JVM参数-XX:+UseSerialGC可以使用串行垃圾回收器。


并行垃圾回收器:

并行垃圾回收器是JVM的默认垃圾回收器

它使用多线程进行垃圾回收

当执行垃圾回收的时候它也会冻结所有的应用程序线程。

-XX:+UseParallelGC:并行垃圾回收器 

 


G1垃圾回收器:

G1垃圾回收器将堆内存分割成不同的区域,并且并发的对其进行进行垃圾回收。

G1垃圾回收会优先选择第一块垃圾最多的区域,它适用于堆内存很大的情况。 

通过JVM参数–XX:+UseG1GC使用G1垃圾回收器