快捷搜索:  汽车  科技

java内存回收分析命令(jvm内存结构及垃圾回收)

java内存回收分析命令(jvm内存结构及垃圾回收)Java 堆还被分为年轻代、老年代两个区域,年轻代还被进一步划分为 Eden 区、From Survivor 0、To Survivor 1 区。并且默认的虚拟机配置比例是Eden:from :to = 8:1:1 。简单来说就是:Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。栈内存溢出最常见的错误就是StackOverflowError,程序有递归调用时候最容易发生方法区 与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫

JVM被分为三个主要的子系统:类加载器子系统、运行时数据区和执行引擎

java内存回收分析命令(jvm内存结构及垃圾回收)(1)

jvm内存结构

一,jVM虚拟机内存结构: JVM在Java程序运行时把它所管理的内存划分为几个不同的数据区域:程序计数器(Program Counter Register)、虚拟机栈(VM Stack)、本地方法栈(Native Method Stack)、 方法区(Method Area)、堆(Heap)。

Java虚拟机栈 ( Java Virtual Machine Stacks)是线程私有的,生命周期与线程相同。虚拟机栈描述的是java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

栈内存溢出最常见的错误就是StackOverflowError,程序有递归调用时候最容易发生

方法区 与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆),目的是与ava堆区分开来。

方法区JDK1.7的时候叫做永久代,到JDK1.8之后废弃了永久代改为元空间(meta space);更新原因:
1、字符串存在永久代中,容易出现性能问题和内存溢出。
2、类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代(就小了)溢出。
3、永久代会为 GC 带来不必要的复杂度,并且回收效率偏低

Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。

Java 堆还被分为年轻代、老年代两个区域,年轻代还被进一步划分为 Eden 区、From Survivor 0、To Survivor 1 区。并且默认的虚拟机配置比例是Eden:from :to = 8:1:1 。简单来说就是:

Java堆 = 老年代 新生代

新生代 = Eden S0 S1 默认 Eden:from :to = 8:1:1

堆内存不够最常见的错误就是OOM(OutOfMemoryError)

运行时常量池 (Runtime Constant Pool)是方法区的一部分Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池(Constant Pool Table ),用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。

本地方法栈( Native Method Stack)与虚拟机栈所发挥的作用是非常相似的,它们之间的区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务。

程序计数器:当前线程所执行的字节码的行号指示器,用于记录正在执行的虚拟机字节指令地址,线程私有

非堆区

Metaspace= Class.Package、Method. Field、字节码、常量池、符号引用等等

• CCs:32位指针的Class

• CodeCache:JIT编译后的本地代码、JN!使用的C代码

-XX:NewSize-XX:MaxNewSize 新生代大小

-XX:NewRatio yong区与old区比例

-XX:SurvivorRatio eden区与surv区比例

-XX:MetaspaceSize-XX:MaxMetaspaceSize

以下两个一般不需要调

-XX: UseCompressedClassPointers

是否启用压缩指针

-XX:CompressedClassSpaceSize

压缩类空间大小

二,垃圾回收算法有哪些?:

引用计数法,

可达性分析法: 枚举跟节点,做可达性分析

跟节点: 类加载器,thread 虚拟机的本地变量表,static 成员,常量引用,本地方法栈的变量等

标记清除:算法分为 “标记〞和“清除〞两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有。

缺点:效率不高。标记和清除两个过程的效率都不高。产生碎片。碎片太多会导致提前GC。

复制: 它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。

优缺点:实现简单,运行高效,但是空间利用率低

标记整理:标记过程仍然与 “标记-清除〞算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存

优缺点:没有了内存碎片,但是整理内存比较耗时。

三,新生代使用什么垃圾回收算法及对象如何分配?

Young区用复制算法

old区用标记清除或者标记整理

对象分配:对象优先在Eden区分配

•大对象直接进入老年代:-XX:PretenureSizeThreshold

•长期存活对象进入老年代:-Xx:Max TenuringThreshold

-XX: PrintTenuring Distribution -XX:TargetSurvivorRatio

四,垃圾收集器有哪些?:

• 串行收集器Serial :Serial Serial old

•并行收集器Parallel :Parallel Scavenge、Parallel old,吞吐量

•并发收集器Concurrent:CMS、 G1, 停顿时间

并行( Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。适合科学计算、后台处理等弱交互场景

并发(Concurrent):指用户线程与垃圾收集线程同时执行(但一定是并行的,可能会交替执行),垃圾收集线程在执行的时候不会停顿用户程序的运行。适合对响应时间有要求的场景,比如Web.

停顿时间和吞吐量:

停顿时间:垃圾收集器做垃圾回收中断应用执行的时间。

XX:MaxGCPauseMillis

吞吐量:花在垃圾收集的时间和花在应用时间的占比。

xx:GCTimeRatio=<n>,垃圾收集时间占:1/1 n

开启串行收集器指令: -XX: UseSerialGC -XX: UseSerialoldGC

并行收集器:吞吐量优先

• -XX: UseParallelGC -XX UseParallelOldGC

-xx: UseParallelGC 手动开启, Server默认开启

-Xx:Paralle GCThreads=<N~多少个GC线程

CPU>8 N=5/8

CPU <8 N=CPU

自适应

-XX:MaxGCPauseMillis=<N>

-XX:GCTimeRatio=<N>

-Xmx<N>

动态内存调整

-XX:YoungGenerationSizelncrement=<Y>

-XX:TenuredGenerationSizelncrement=<T>

-XX:AdaptiveSizeDecrementScaleFactor=<D>

并发收集器:响应时间优先

• CMS : XX: UseConcMarkSweepGC -XX: UseParNewiGC

• G1: -XX: UseG1GC

cms相关参数: 低停顿,低延迟,老年代收集器

-xX:ConcGCThreads:并发的GC线程数

-xX: UseCMSCompactAtFullCollection: FullGC之后做压缩

-xX:CMSFullGCs BeforeCompaction :多少次FullGC之后压缩一次

-xX:CMSinitiatingOccupancyFraction:触发FullGC

-Xx: UseCMSinitiatingOccupancyonly:是否动态调

-XX: CMSScavenge BeforeRemark :FullGC之前先做YGC

G1:新生代和老生代收集器 Jdk9默认收集器

• Region

SATB : Snapshot-At-The-Beginning,它是通过Root Tracing得到的,GC开始时候存活对象的快照。

RSet :记录了其他Region中的对象引用本Region中对象的关系,属于points-into结构(谁引用了我的对象)

YGC和其他收集器一样:

•新对象进入Eden区

•存活对象拷贝到Survivor区

存活时间达到年龄间值时,对象晋升到Old区

MixedGC

-XX: UseG1GC 开启G1

-xx:G1HeapRegionSize=n region的大小,1-32M 2048个

-xx:MaxGCPauseMillis=200 最大停顿时间

4.-XX:G1NewSizePercent -XX:G1MaxNewSizePercent

-Xx:G1ReservePercent=10 保留防止to space溢出

-xx:Parallel GCThreads=n SWT线程数

- Xx:ConcGCThreads=n 井发线程数=1/4*并行

五,GC最佳实践

轻代大小:避免使用-Xmn.

-xx:NewRatio等显式设置young区大小,会覆盖暂停时间目标。

暂停时间目标 :暂停时间不要太严苛,其吞吐量目标是90%的应用程序时间和10%的垃圾回收时间,太严苛会直接影响到吞吐量

## GC调优日志步骤

•打印GC日志: 根据日志得到关键性能指标

•分析GC原因,调优JVM参数

六,实战GC调优

初始设置

-xx: DisabieExplicitGC -XX: HeapDumpOnoutofMemory Error

Xxx:HeapDumpPath=$CATALINA_HOME/10g$/ -xx: PrintGCDetails

Xx: PrintGCTimeStamps -xx: PrintGCDate Stamps •

Xloggc:$CATALINA_HOME/logs/gc.log

Parallel GC调优的指导原则

•除非确定,否则不要设置最大堆内存

•优先设置吞吐量目标

如果吞吐量目标达不到,调大最大内存 ,不能让OS使用Swap,如果仍然达不到,降低目标。吞吐量能达到,GC时间太长,设置停顿时间的目标。

猜您喜欢: