深入理解JVM(学习过程) (24)

image-20200216070228154

线程栈溢出监控与Jconsole 工具使用介绍 /** 虚拟机栈溢出 举例:使用递归,可能导致栈溢出。 */ public class MyTest2 { private int length; //记录一共调用了多少层。 public void setLength(int length) { this.length = length; } public int getLength() { return length; } public void test(){ this.length ++; test(); } public static void main(String[] args) { MyTest2 myTest2 = new MyTest2(); try{ myTest2.test(); }catch(Throwable ex ){ System.out.println(myTest2.length); ex.printStackTrace(); } } } // 在 vm options中添加参数: -Xss160k // 设置栈的大小为160k(JVM虚拟机要求的最小栈内存为160k) 运行结果如下图。

image-20200216095202893

image-20200216095139957

Jvisualvm 监控栈溢出过程。

image-20200216095554940

Jconsole 工具 监控。 也是Oracle自带的。

image-20200216100604706

线程死锁检测与分析工具深度学习 //自己编写一个可以产生死锁的代码。使用Jconsole检测死锁。 public class MyTest3 { public static void main(String[] args) { new Thread(A::method,"ThreadA").start(); //使用lambda表达式启动线程. new Thread(B::method,"ThreadB").start(); } } class A{ public static synchronized void method(){ // 当方法持有锁时,线程过来时检测的锁是当前class的锁。 System.out.println("method from A"); try { Thread.sleep(5000); B.method(); } catch (InterruptedException e) { e.printStackTrace(); } } } class B{ public static synchronized void method(){ System.out.println("method from B"); try { Thread.sleep(5000); A.method(); } catch (InterruptedException e) { e.printStackTrace(); } } } ThreadA 和 ThreadB 是main的子线程。 // 启动程序后,检测死锁,检测到了。结果如下图所示。

使用Jconsole检测死锁的结果。

image-20200216100604706

使用jvisualvm工具检测的结果:

image-20200216102553738

image-20200216102855414

方法区产生内存溢出错误 /** 方法区产生内存溢出错误 // 在方法区产生错误是极难的,有两种手段。 1. 要手动设置元空间的大小,让元空间不会自动扩展。(jdk默认的元空间大小是21M。如果超过了之后,默认的会自动进行垃圾回收,之后会自动扩展元空间的大小。) 2. 要明确的知道元空间存放的信息。存放的是元信息,并不存放对象实例。对象实例是存在堆上边的。我们可以采取特殊的手段让对象实例存放在元信息上。使用动态代理的方式创建出来的元信息是放在元空间当中的(使用cjlib库来操作的)。 */ '操作步骤' // 1. 添加依赖: cglib:cglib:3.2.8 // 2. 代码如下第一图 // 3. 设置元空间的大小: VM options : -XX:MaxMetaspaceSize = 10M // 4. 输出结果为下方第二图。

image-20200216104133763

image-20200216104328690

使用jconsole来进行检测:

image-20200216104624696

使用jvisoualvm进行检测: 能够明确的看到元空间使用了多少M

image-20200216105008572

元空间的概念

原文链接:https://www.infoq.cn/article/Java-PERMGEN-Removed/

image-20200216105741362

image-20200216105714487

image-20200216105838292

image-20200216105951254

image-20200216110141517

适当监控工具的实践

存在两种工具。(图示化工具能看到的,命令行都可以得到。)

命令行工具 : jmap ; jstat ; jcmd ;jhat

GUI工具: jconsole ; jvisoualvm ;jmc

jmap 工具介绍

image-20200216113233697

image-20200216112503752

jstat 工具介绍

image-20200216113317660

image-20200216113503081

上图中的MC的作用:当前的元空间的容量

MU:元空间已经被使用的容量

jcmd 命令介绍和 jps命令

jps 命令: 查看当前左右线程的pid .

jcmd 和 jps 配合使用,查看JVM的多种信息 。 PID等

jcmd (从jdk1.7开始新增的命令)命令介绍:

jcmd pid VM.flags : 查看JVM的启动参数

jcmd pid help : 列出当前运行的Java进程可以进行的操作。

jcmd pid help JFR.dump: 查看当前命令的具体操作含义

jcmd pid PerfCounter.pring: 查看JVM性能相关的参数

jcmd pid VM.uptime: 查看 JVM的启动时长

jcmd pid GC.class_histogram : 查看系统当中类的统计信息

jcmd pid Thread.print : 查看当前线程的堆栈信息。

jcmd pid GC.head_dump path : 查看当前堆的信息,并打印到path路径

jcmd pid VM.system_properties : 查看JVM的属性信息。

jcmd pid VM.version: 查看目标进行JVM版本的信息。

jcmd pid VM.command_line : 命令行的参数

jstack pid : 查看或者导出当前线程的堆栈信息。

命令行:jps : 查看PID

image-20200216114145788

jcmd 和 jps 配合使用,查看JVM的多种信息

image-20200216114538731

jmc命令 - 可视化工具

jmc : JAVA Mission Conreol

jfr : java flight recodrding 飞行记录器

我本地不能打开。

image-20200216173617561

image-20200216173652966

jhat 对于堆转储的分析

功能和visualvm类似。涉及到了OQL 对象查询语言,随用随查即可。

image-20200216174439926

来一个系统性的总结与回顾

ClassLoader

Java字节码

JVM的内存空间

2020年02月17日20:58:02 复习结束。开始新的课程啦。

垃圾回收 垃圾回收基础概念介绍

垃圾回收最主要的是在堆中进行的。- - 了解了垃圾回收的原理,才能写出来更高效的代码。

JVM运行时内存数据区域

image-20200217210008919

个人理解:

灰色区域为线程共享的,白色区域为线程隔离。

方法区:存放元数据信息。常量池空间就在这个里边。

本地方法栈:存放navtion的,非Java代表编写的本地方法。

Java虚拟机栈(栈帧):存放对象的引用

堆:创建的对象存储在这里边。

image-20200217210403016

image-20200217210432667

image-20200217210531570

JVM垃圾回收(GC)模型

image-20200217210842193

垃圾判断的算法

image-20200217210856009

引用计数算法

image-20200217210911714

什么是无法解决对象循环引用的问题。

已经没有外部的引用引用这两个对象了,是一个完全孤立的系统,但是这个两个对象又相互引用。所以这两个对象一直无法被回收。

image-20200217211248678

根搜索算法

image-20200217211335917

image-20200217211451800

方法区

image-20200217211546895

image-20200217211619064

image-20200217211839428

JVM常见GC算法

每一种算法都有自己的好处与缺点

image-20200217211903176

新生代,一般使用复制算法。

老年代,一般使用标记算法。

(选取算法的根据是 1、生命周期 2、有一个老年代作为分配担保的后盾 )

标记-清除算法

image-20200217212048099

image-20200217212308066

上图中有引用的如下图所示,绿色的是垃圾回收时不会回收的,红色的是被回收的内容。

image-20200217212442454

执行完一次垃圾回收之后,结果如下图所示。

image-20200217212537982

image-20200217212547976

复制收集算法

image-20200217212646498

image-20200217212851458

image-20200217213143347

image-20200217213229766

复制后的样子:

image-20200217213319395

垃圾回收后的样子

image-20200217213411692

image-20200217213432398

标记-整理算法

image-20200217213853257

​ 示意图:

image-20200217213928751

image-20200217213952602

image-20200217214019697

分代收集算法

image-20200217214129412

image-20200217214324773

image-20200217214508783

image-20200217214550859

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpfdfy.html