java虚拟机内存告警_Java虚拟机总结

本文详细介绍了Java虚拟机的类加载机制,包括加载、链接和初始化的步骤,以及类加载器的工作原理。接着讲解了JVM内存结构,如堆、方法区、程序计数器等,并探讨了对象分配规则。接着深入讨论了垃圾回收(GC)算法,如标记-清除、复制、标记-整理和分代收集,并解析了不同GC算法的特点和应用场景。最后,文章提到了GC日志分析和性能调优的相关工具和命令,以及执行引擎的解释器、JIT编译器和垃圾收集器的角色。
摘要由CSDN通过智能技术生成

JVM体系四大块:

类的加载

JVM内存结构

GC算法 垃圾回收

GC分析 性能调优

执行引擎

JVM架构图

e0fe83ecfabf

jvm.arch

一、类的加载机制

类的加载

类的加载,将class文件读入方法区,然后在堆中创建java.lang.Class对象。类的加载最终是生成堆区中的Class对象。Class对象封装类在方法区中的数据结构,并提供访问方法区中的数据结构的接口。

类的生命周期

类的生命周期包括:加载、连接、初始化、使用和卸载,其中前三步是类的加载过程。

e0fe83ecfabf

class.lifecycle

加载,查找并加载类的二进制数据,在Java堆中创建Class类的对象。

链接,

验证,文件格式、元数据、字节码、符号引用的验证。

准备,为类的静态变量分配内存,并初始化为默认值。

解析,把类中的符号引用转换为直接引用。

初始化,为类的静态变量赋予手动设置的初始值。

使用,new出对象,在程序中使用。

卸载,执行垃圾回收。

几个小问题

1、JVM初始化步骤 ? 2、类初始化时机 ?3、哪几种情况下,Java虚拟机将结束生命周期?

类加载器

启动类加载器:Bootstrap ClassLoader,扩展类加载器:Extension ClassLoader,应用程序类加载器:Application ClassLoader。

类加载机制

全盘负责,当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也由该类加载器负责载入,除非显示使用另外一个类加载器来载入。

父类委托,先让父类加载器尝试加载该类,只有在父类加载器无法加载时才从自己的类路径中加载该类。

缓存机制,缓存机制保证所有加载过的Class都会被缓存。当程序中需要使用某个Class时,类加载器先从缓存区寻找该Class,只有缓存区中不存在,系统才会读取该类对应的二进制数据,并将其转换成Class对象存入缓存区。这就是为什么修改了Class后,必须重启JVM,程序的修改才会生效。

二、JVM内存结构

jvm内存结构

Java堆(Heap),只存放对象实例,几乎所有的对象实例都在这里。

方法区(Method Area),存储已被加载的类信息、常量、静态变量、即时编译器编译后的代码。

程序计数器(Program Counter Register),当前线程所执行的字节码的行号指示器。

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

本地方法栈(Native Method Stacks),与虚拟机栈类似,虚拟机栈为虚拟机执行Java方法(字节码)服务,而本地方法栈为虚拟机使用到的Native方法服务。

对象分配规则

对象优先分配在Eden区,如果Eden区没有足够空间时,执行minor GC。

大对象直接进入老年代。可以避免在eden区和两个survivor区之间发生大量的内存拷贝(新生代采用复制算法收集内存)。

长期存活的对象进入老年代。虚拟机为对象定义了一个年龄计数器,如果对象经过了1次minor GC那么对象会进入survivor区,之后每经过一次minor GC那么对象的年龄加1,直到达到阀值,对象进入老年区。

动态判断对象的年龄。如果survivor区中相同年龄的所有对象大小的总和大于survivor空间的一半,年龄大于或等于该年龄的对象直接进入老年代。

空间分配担保。每次进行minor GC时,JVM计算survivor区移至老年区的对象的平均大小,如果这个值大于老年区的剩余值则进行一次full GC。如果小于检查HandlePromotionFailure参数值,则只进行minor GC,否则进行Full GC。

三、GC算法 垃圾回收

1、对象存活判断方式

引用计数:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时减1,计数为0时可以回收。此方法简单,但无法解决对象循环引用的问题。

可达性分析:从GC roots向下搜索,搜索所走过的路径称为引用链。当对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的,不可达对象。

GC roots包括:虚拟机栈中引用的对象。本地方法栈中JNI引用的对象。 方法区中类静态属性、常量引用的对象。

2、GC算法

标记 -清除(Mark-Sweep)算法,分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后回收所有被标记的对象。

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

标记-整理算法,标记过程与“标记-清除”算法一样,但后续步骤是让所有存活的对象向一端移动,然后清理掉端边界以外的内存。

分代收集算法(Generational Collection),把堆分为新生代和老年代,根据各年代的特点采用适当的收集算法。(**常用)

分区

3、垃圾回收器

Serial回收器,是最古老,最稳定以及效率高的收集器,可能会产生较长的停顿,只能用一个线程回收。

ParNew回收器,ParNew收集器是Serial收集器的多线程版本。

Parallel Scavenge回收器,类似ParNew收集器,Parallel收集器更关注系统的吞吐量。

CMS(Concurrent Mark Sweep)收集器,以获取最短回收停顿时间为目标的收集器。

G1(Garbage-First)收集器,是面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器。以极高概率满足GC停顿时间的同时,还具备高吞吐量。

三、GC分析 性能调优

1、GC日志分析

[GC [: -> , secs] -> , secs] [Times: user=secs sys=secs, real=secs]

GC收集器的名称

新生代在GC前占用的内存

新生代在GC后占用的内存

新生代局部收集时jvm暂停处理的时间

JVM Heap 在GC前占用的内存

JVM Heap 在GC后占用的内存

GC过程中jvm暂停处理的总时间

用户时间

系统时间

实际时间

4.231: [GC 4.231: [DefNew: 4928K->512K(4928K), 0.0044047 secs] 6835K->3468K(15872K), 0.0045291secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

4.445: [Full GC (System) 4.445: [Tenured: 2956K->3043K(10944K), 0.1869806 secs] 4034K->3043K(15872K), [Perm : 3400K->3400K(12288K)], 0.1870847secs] [Times: user=0.05 sys=0.00, real=0.19 secs]

最前面的数字 4.231 和 4.445 代表虚拟机启动以来的秒数。

接下来的 [DefNew , [Tenured , [Perm 表示 GC 发生的区域,区域的名称与使用的 GC 收集器相关。 Serial 收集器中新生代名为 "Default New Generation",显示的名字为 "[DefNew"。ParNew收集器显示的是 "[ParNew", “Parallel New Generation”。 Parallel Scavenge 收集器新生代名为 "PSYoungGen"。年老代和永久代名称也都由收集器决定。

方括号内部显示的 “4928K->512K(4928K)” 表示 “GC 前该区域已使用容量 -> 垃圾回收后该区域已使用容量 (该区域内存总容量) ”。

再往后的 “0.0044047 secs” 表示该区域GC所用时间,单位是秒。

再往后的 “6835K->3468K(15872K)” 表示 “GC 前Java堆已使用容量 -> GC后Java堆已使用容量 (Java堆总容量)”。

再往后的 “0.0045291 secs” 是Java堆GC所用的总时间。

最后的 “[Times: user=0.00 sys=0.00, real=0.00 secs]” 分别代表用户态消耗的CPU时间、内核态消耗的CPU时间和操作从开始到结束所经过的墙钟时间。

墙钟时间包括各种非运算的等待耗时,如IO等待、线程阻塞。CPU时间不包括等待时间,当系统有多核时,多线程操作会叠加这些CPU时间,所以user或sys时间会超过real时间。

2、调优命令

JDK监控和故障处理命令

jps,显示指定系统内所有的HotSpot虚拟机进程。

jstat,用于监视虚拟机运行时状态信息,可以显示出虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。

jmap,生成heap dump文件。

jhat,与jmap搭配使用,分析jmap生成的dump,jhat内置了一个微型的HTTP/HTML服务器,生成dump的分析结果后,可以在浏览器中查看。

jstack,生成java虚拟机当前时刻的线程快照。

jinfo,实时查看和调整虚拟机运行参数。

3、调优工具

常用调优工具分为两类,jdk自带监控工具:jconsole和jvisualvm;第三方有:MAT(Memory Analyzer Tool)。

jconsole,是从java5开始,JDK自带的java监控和管理控制台,用于对JVM中内存,线程和类等的监控。

jvisualvm,jdk自带全能工具,可以分析内存快照、线程快照;监控内存变化、GC变化等。

MAT,Memory Analyzer Tool,基于Eclipse的内存分析工具,是一个快速、功能丰富的Java heap分析工具,它可以帮助我们查找内存泄漏和减少内存消耗。

四、执行引擎

分配给运行时数据区的字节码将由执行引擎执行,执行引擎读取字节码并逐个执行。

(1) 解释器:解释器更快地解释字节码,但执行缓慢。解释器的缺点是当一个方法被调用多次时,每次都需要一个新的解释。

(2) JIT编译器:JIT编译器消除了解释器的缺点。执行引擎将在转换字节码时使用解释器的帮助,但是当它发现重复的代码时,将使用JIT编译器,编译整个字节码并将其更改为本地代码。这个本地代码将直接用于重复的方法调用,这提高了系统的性能。JIT的构成组件为:

中间代码生成器(Intermediate Code Generator):生成中间代码。

代码优化器(Code Optimizer):优化上面生成的中间代码。

目标代码生成器(Target Code Generator):生成机器代码或本地代码。

分析器(Profiler):查找热点,即该方法是否被多次调用。

(3) 垃圾收集器(Garbage Collector):收集和删除未引用的对象。可以通过调用“System.gc()”触发垃圾收集,但不保证立即执行。

Java本机接口(JNI):JNI与本机方法库进行交互,并提供执行引擎所需的本机库。

本地方法库(Native Method Libraries):它是执行引擎所需的本机库的集合。

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值