JVM调优

一 JVM内存区域

在这里插入图片描述

1.1堆(Java Heap)

堆是所有类实例和数组的内存分配的运行时数据区。
虚拟机启动时创建。
堆可以为固定大小或动态扩展
堆的内存逻辑连续,物理不连续
堆是线程共享的
对象的堆存储由垃圾收集器回收

1.2 堆栈(Program Counter Register)

Java虚拟机堆栈存储帧。包含局部变量和部分结果,并在方法调用和返回中扮演角色。
每个线程都有一个私有Java虚拟机堆栈,同时创建线程的堆栈
堆栈可以为固定大小或动态扩展
堆栈是线程不共享的

1.3 本地方法栈(Native Method Stacks)

与虚拟机栈类似,为Native方法服务。一般是java调用其他语言时使用。

1.4 方法区(Method Area)

存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。
可以为固定大小或动态扩展
方法区是线程共享的
方法区可以不被垃圾收集器回收

1.5 运行时常量池(Runtime Constant Pool)

存放编译器生成的各种字面量和符号引用以及直接引用。
方法区的一部分。

1.6 程序计数器(Program Counter Register)

当前线程所执行的字节码的行号指示器。
字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。

1.7 直接内存(Direct Memory)

非虚拟机运行时内存
基于通道与缓冲区的NIO模式下,直接内存可以使用native函数库直接分配堆外内存,然后通过一个存
储在java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。避免java堆和natice堆中来回复制
数据

1.8 内存模型特征对比

二 对象创建

2.1 创建过程

1.检查是否加载过
虚拟机解析new指令,首先检查常量池是否有类的符号引用,并且检查是否已经加载解析和初始化,没
有就执行类加载过程
2.分配内存
虚拟机在java堆中分配空间。如果内存是规整的,虚拟机通过“指针碰撞”分配内存、如果内存不规整
的,虚拟机维护一个内存块使用情况表,通过“空闲列表”分配内存。
3.初始化
内存空间初始化为零值。这也是有些对象不赋值就可以使用的原因。
4.设置对象头
在对象的对象头中设置:对象是哪个类的实例,如何找到类的元数据信息、对象的哈希码、对象的Gc分
带年龄等信息。
5.执行init指令
以上4步一个新的对象已经产生,但是所有的字段都是零。接着字节码解析器调用init指令,这个对象才
算完全产生出来。

2.2 对象的内存布局

1.对象头
1.1、运行时数据包括哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向锁ID和
偏向时间戳等,这部分数据在32位和64位虚拟机中的长度分别为32bit和64bit,官方称为"Mark
Word"。Mark Word被设计成非固定的数据结构,以实现在有限空间内保存尽可能多的数据。
32位的虚拟机中,对象未被锁定的状态下,Mark Word的32bit中25bit存储对象的HashCode、4bit存
储对象分代年龄、2bit存储锁标志位、1bit固定为0,具体如下:
其它状态(轻量级锁定、重量级锁定、GC锁定、可偏向锁)下Mark Word的存储内容如下:
1.2、对象头的类型指针指向该对象的类元数据,虚拟机通过这个指针可以确定该对象是哪个类的实
例。
2.实例数据
实例数据就是在程序代码中所定义的各种类型的字段,包括从父类继承的,这部分的存储顺序会受到虚
拟机分配策略和字段在源码中定义顺序的影响。
3.对齐填充
由于HotSpot的自动内存管理要求对象的起始地址必须是8字节的整数倍,即对象的大小必须是8字节的
整数倍,对象头的数据正好是8的整数倍,所以当实例数据不够8字节整数倍时,需要通过对齐填充进行
补全。

三 溢出分析

3.1 溢出区域

内存溢出分为内内存溢出和栈内存溢出
如果虚拟机在扩展栈时无法申请到足够大的内存空间时,就会抛出outOfMemoryError
如果线程请求的栈深度大于虚拟机所允许的最大深度,则抛出StackOverflowError

四 垃圾检测算法

4.1 引用计数法

通过判断对象的引⽤数来决定对象是否可以被回收
优点:
实现简单,垃圾对象便于标识;
判定效率⾼,回收没有延迟性。
缺点:
它需要单独的字段存储计数器,这样的做法增加了存储空间的开销。
每次赋值都需要更新计数器,伴随这加法和减法操作,这就增加了时间开销。
致命缺陷,即⽆法处理循环引⽤的情况。导致在java的垃圾回收器中没有使⽤这类算法。

4.2 可达性分析

在这里插入图片描述
可达性分析算法是通过判断对象的引⽤链是否可达来决定对象是否可以被回收。

五 垃圾回收算法

5.1 标记清除算法(Mark-Sweep)

特点:实现简单,但是有内存碎片
在这里插入图片描述

5.2 复制算法(copying)

无内存碎片,但是内存利用率低
在这里插入图片描述

5.3 标记整理算法(Mark-Compact)

特点:没有内存碎片,内存利用率也高,但是算法相对比较复杂
在这里插入图片描述

5.4 分代收集算法

JVM内存中的堆是垃圾回收的主要区域,分为新生代和老年代
在这里插入图片描述

六 垃圾回收器

串⾏回收器: Serial 、 Serial Old
并⾏回收器: ParNew、 Parallel Scavenge、 Parallel Old
并发回收器: CMS、 G1
在这里插入图片描述
在这里插入图片描述

6.1 CMS回收器(标记清除)

Ø初始标记:stop-the-world,标记GCRoots直接关联的对象
Ø并发标记:并发追溯标记,程序不会停顿
Ø重新标记:暂停虚拟机,扫描CMS堆中的剩余对象
Ø并发清理:清理垃圾对象,程序不会停顿
Ø并发重置:重置CMS收集器的数据结构
在这里插入图片描述
CMS主要优点:
1.并发收集;
2.低停顿。
CMS明显的缺点:

  1. CMS收集器对CPU资源⾮常敏感。 在并发阶段,它虽然不会导致⽤户线程停顿,但是会因为占⽤
    了⼀部分线程⽽导致应⽤程序变慢,总吞吐量
  2. CMS收集器⽆法处理浮动垃圾,可能出现“Concurrent Mode Failure”失败⽽导致另⼀次Full GC
    的产⽣。
  3. CMS是基于“标记-清除”算法实现的收集器,收集结束时会有⼤量空间碎⽚产⽣

6.2 G1垃圾收集器(标记整理算法)

1、G1垃圾收集器将整个 JVM 内存分为多个大小相等的
region,年轻代和老年代逻辑分区 。
2、G1 是 Java9 以后的默认垃圾回收器了
3、G1 在整体上使用标记整理算法,局部使用复制算法
4、G1 的每个 Region 大小在 1-32M 之间,可以通过
-XX:G1HeapRegionSize=n 指定区大小。
5、总的 Region 个数最大可以存在 2048 个,即heap最
大能够达到32M*2048=64G
6、0.5<obj<1,那么放到old区,old标记为H
1<obj<n,连续的n个region,作为H
l 概念
Ø rset:每个region都有一个叫做rset的小区,它代表了其他region引用了当前region
对象的记录
Ø cset:本次GC需要清理的Region集合
l mixGC的过程
Ø初始标记:标记出GCRoot对象,以及GCRoot所在的Region(RootRegion)
ØRoot Region Scanning:扫表整个old的Region
Ø并发标记:并发追溯标记,进行GCRootsTracing的过程
Ø最终标记:修正并发标记期间,因程序运行导致标记发生变化的那一部分对象
Ø清理回收:根据时间来进行价值最大化的回收,重置rset

G1收集器的优点
与其他GC收集器相⽐, G1使⽤全新的分区算法,其特点如下所示:

  1. 并⾏与并发
    并⾏性: G1在回收期间,可以有多个GC线程同时⼯作,有效利⽤多核计算能⼒。此时⽤户线程
    STW。
    并发性:G1拥有与⽤户线程交替执⾏的能⼒,部分⼯作可以和应⽤程序同时执⾏。因此,⼀般来
    说,不会再整个回收阶段发⽣完全阻塞应⽤程序的情况。
    2)分代收集
  2. 可预测的停顿时间模型(即:软实时 soft real time)
    G1收集器的缺点
    相对于CMS, G1还不具备全⽅位、压倒性优势。⽐如在⽤户程序运⾏过程中, G1⽆论是为垃圾收
    集产⽣的内存占⽤还是程序运⾏时的额外执⾏负载都要⽐CMS要⾼。
    从经验上来说,
    整体⽽⾔:
    ⼩内存应⽤上, CMS ⼤概率会优于 G1;
    ⼤内存应⽤上, G1 则很可能更胜⼀筹。
    这个临界点⼤概是在 6~8G 之间(经验值)

6.2.1 G1相关的参数配置

-XX:+UseG1GC :设置使用 G1 垃圾回收器
-XX:MaxGCPauseMillis=n :最大 GC 停顿时间,毫秒值
-XX:InitatingHeapOccupancyPercent=n:当堆空间占用到 n 兆时就触发 GC(45)
-XX:GoncGCThreads=n:并发 GC 使用的线程数
-XX:G1ReserverPercent=n:设置作为空闲空间的预留内存百分比(10%)

七 调优

7.1 垃圾回收器的选择

-XX:+UseXXXGC

7.2 参数的设置

-XX:PermSize 永久区
-Xms 堆初始值
-Xmx 堆最大值
-XX:NewRatio 年轻代和年老代比率
-XX:SurvivorRatio Eden区与Survivor区的比值
1、堆内存设置
-Xms16g:设置初始堆内存为16GB,为系统内存的一半,确保系统有足够的内存用于非堆内存和操作系统本身。
-Xmx16g:设置最大堆内存也为16GB,有助于减少堆内存的动态调整。
2、垃圾收集器选择
-XX:+UseG1GC:使用G1垃圾收集器,适合于大堆内存和多核处理器的场景,可以提供平衡的吞吐量和较低的延迟。
3、G1垃圾收集器的进一步优化
-XX:MaxGCPauseMillis=200:设置期望的最大GC暂停时间(毫秒),以便于优化延迟。
-XX:ParallelGCThreads=8:设置并行垃圾收集线程数。一般设置为可用CPU核心数。
-XX:ConcGCThreads=4:设置G1的并发标记线程数,一般为ParallelGCThreads的一半。
4、元空间(Metaspace)
-XX:MetaspaceSize=256m:设置初始元空间大小,元空间用于存放类元数据。
-XX:MaxMetaspaceSize=512m:设置最大元空间大小,以限制其无限增长可能导致的问题。
5、日志和监控
-XX:+PrintGCDetails:打印详细的GC日志。
-XX:+PrintGCDateStamps:为GC日志添加时间戳。
-Xloggc:/var/log/yourapp-gc.log:将GC日志写入指定文件。
-XX:+UseGCLogFileRotation:开启GC日志文件的轮替。
-XX:NumberOfGCLogFiles=5:指定GC日志文件的数量。
-XX:GCLogFileSize=20M:指定GC日志文件的大小。
6、JVM性能调优
-XX:+UseStringDeduplication:开启JVM字符串去重功能,有助于减少堆内存的占用。
-XX:+DisableExplicitGC:禁用System.gc()的显式调用,避免可能的性能问题。

7.3 调优-工具

1 jps
主要是看虚拟机的相关参数配置
2 jstat
类加载,内存,垃圾收集,jit编译信息
3 jinfo
实时调整和查看虚拟机参数
4 jmap
侧重查看内存信息
5 jstack
线程堆栈信息
6 jconsole和jvisualvm工具

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值