
线程栈溢出监控与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)
运行结果如下图。


Jvisualvm 监控栈溢出过程。

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

线程死锁检测与分析工具深度学习
//自己编写一个可以产生死锁的代码。使用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检测死锁的结果。

使用jvisualvm工具检测的结果:


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


使用jconsole来进行检测:

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

元空间的概念
原文链接:https://www.infoq.cn/article/Java-PERMGEN-Removed/





适当监控工具的实践
存在两种工具。(图示化工具能看到的,命令行都可以得到。)
命令行工具 : jmap ; jstat ; jcmd ;jhat
GUI工具: jconsole ; jvisoualvm ;jmc
jmap 工具介绍


jstat 工具介绍


上图中的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

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

jmc命令 - 可视化工具
jmc : JAVA Mission Conreol
jfr : java flight recodrding 飞行记录器
我本地不能打开。


jhat 对于堆转储的分析
功能和visualvm类似。涉及到了OQL 对象查询语言,随用随查即可。

来一个系统性的总结与回顾
ClassLoader
Java字节码
JVM的内存空间
2020年02月17日20:58:02 复习结束。开始新的课程啦。
垃圾回收
垃圾回收基础概念介绍
垃圾回收最主要的是在堆中进行的。- - 了解了垃圾回收的原理,才能写出来更高效的代码。
JVM运行时内存数据区域

个人理解:
灰色区域为线程共享的,白色区域为线程隔离。
方法区:存放元数据信息。常量池空间就在这个里边。
本地方法栈:存放navtion的,非Java代表编写的本地方法。
Java虚拟机栈(栈帧):存放对象的引用
堆:创建的对象存储在这里边。



JVM垃圾回收(GC)模型

垃圾判断的算法

引用计数算法

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

根搜索算法


方法区



JVM常见GC算法
每一种算法都有自己的好处与缺点

新生代,一般使用复制算法。
老年代,一般使用标记算法。
(选取算法的根据是 1、生命周期 2、有一个老年代作为分配担保的后盾 )
标记-清除算法


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

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


复制收集算法




复制后的样子:

垃圾回收后的样子


标记-整理算法

示意图:



分代收集算法



