JProfiler 是一个 用于分析运行JVM内部情况的专业工具。 在开发中你可以使用它,用于质量保证,也可以解决你的生产系统遇到的问题
JProfiler处理四个主要问题:
方法调用
这通常被称为"CPU分析"。方法调用可以通过不同的方式进行测量和可视化, 分析方法调用可以帮助了解你的应用程序正在做什么,并找到提高其性能的方法。
分配
分析堆上对象的分配、引用链和垃圾回收属于"内存分析"的范畴。 这个功能可以让你解决内存泄漏,总之使用更少的内存,分配更少的临时对象。
线程和锁
线程可以持有锁,例如通过在一个对象上做同步。当多个线程协作时,可能会出现死锁,JProfiler可以为你可视化这种情况。 此外,锁可能被争用,这意味着线程在获得锁之前必须等待。通过JProfiler可以深入了解线程及其各种锁情形。
高层子系统
许多性能问题发生在更高的语义层面。例如,对于JDBC调用,你可能想找出哪条SQL语句是最慢的。 对于这样的子系统,JProfiler提供了"探针",将特定有效载荷附加到调用树。
JProfiler的UI是一个桌面应用程序。你可以以交互的方式实时分析JVM,也可以在不使用UI的情况下,自动化分析。 保存在快照中的分析数据,可以通过JProfiler UI打开。此外,命令行工具和构建工具集成可以帮助你自动分析会话。
OOM错误
import java.util.ArrayList;
//-Xms 设置初始化内存大小,默认是1/64
//-Xms 设置最大分配内存,默认是1/4
//-XX:+PrintGCDetail 打印GC垃圾回收的相关信息
//-XX:+HeapDumpOnOutOfMemoryError 打印OOM的错误,并Dump
//-Xms1m -Xms8m -XX:+HeapDumpOnOutOfMemoryError
public class Demo03 {
byte[] bytes = new byte[1*1024*1024];
public static void main(String[] args) {
ArrayList<Demo03> objects = new ArrayList<>();
int count = 0;
try {
while (true) {
objects.add(new Demo03());
count++;
}
} catch (Exception e) {
System.out.println(count);
System.out.println(e.getMessage());
}
}
}
下载JProfiler
无脑式下一步安装即可
然后IDEA下载 Jprofiler插件

下载完后程序我们去tools配置下载的客户端Jprofiler
IDEA会自动配置

在执行程序时加上以下参数

执行完毕后会dump下来文件

打开项目根目录找到dump文件

打开分析错误

import java.util.Random;
public class Test {
public static void main(String[] args) {
//返回虚拟机试图使用的最大内存
long max = Runtime.getRuntime().maxMemory();
//返回虚拟机的初始化内存
long totalMemory = Runtime.getRuntime().totalMemory();
System.out.println("虚拟机试图使用的最大内存:" + max + "字节," + ((double)max/1024/1024) + "MB");
System.out.println("虚拟机的初始化内存:" + totalMemory + "字节," + ((double)totalMemory/1024/1024) + "MB");
//在启动时配置JVM参数
//-Xms8m -Xms8m -XX:+PrintGCDetails
//伊甸园区+老年区=堆内存 元空间 逻辑上存在,物理上不存在
//305664K + 699392K = 1,005,056K = 981.5MB
//默认情况下,分配的总内存 是电脑内存的 1/4 而初始内存是 1/64
//OOM错误解决
//1.尝试扩大堆内存,看结果
//2.分析内存,看那个地方出现了问题(专业工具)
}
}

设置JVM参数启动
import java.util.Random;
public class Test {
public static void main(String[] args) {
//返回虚拟机试图使用的最大内存
long max = Runtime.getRuntime().maxMemory();
//返回虚拟机的初始化内存
long totalMemory = Runtime.getRuntime().totalMemory();
System.out.println("虚拟机试图使用的最大内存:" + max + "字节," + ((double)max/1024/1024) + "MB");
System.out.println("虚拟机的初始化内存:" + totalMemory + "字节," + ((double)totalMemory/1024/1024) + "MB");
//-Xms8m -Xms8m -XX:+PrintGCDetails
//伊甸园区+老年区=堆内存 元空间 逻辑上存在,物理上不存在
//305664K + 699392K = 1,005,056K = 981.5MB
}
}
设置JVM参数

单击 modiy options

选择JVM参数

写入参数名称

Apply同意并保存
执行代码

我们可以得出,伊甸园区内存大小+老年代内存大小=981.5
所以说,元空间,逻辑上存在,物理上不存在

JVM在进行GC垃圾回收时,并不是对这三个区域同意回收,大部分回收都是新生代
GC两种类型:轻GC(普通的GC) 重GC(全局GC)
GC题目:



好处:没有内存的碎片
坏处:浪费了内存空间,多了一半空间永远是空的。假设对象100%存活(极端情况)
复制算法最佳使用场景:对象存活度较低的时候;新生区~

优点: 不需要额外的空间,把复制算法的缺点弥补了
缺点: 两次扫描严重浪费时间,会产生内存碎片,hash定位需要成本
再次优化

先标记清除几次

再压缩

内存效率:复制算法 —> 标记清除算法 —> 标记压缩算法(时间复杂度)
内容整齐度:复制算法 = 标记压缩算法 —> 标记清除算法
内容利用率:标记压缩算法 = 标记清除算法 —> 复制算法
没有最优算法吗?
没有,没有最好的算法,只有最合适的算法, —> GC:分代收集算法
年轻代:
老年代:
什么是JMM:Java Memory Model
它是干嘛的?:官方,博客,对应的视频
作用:缓存一致性协议,用于定义数据读写的规则(遵守,找到规则)
JMM定义了线程工作内存和主内存之间的抽象关系:线程之间的共享变量存储在主内存中(Main Memory)中,
每个线程都有一个私有的工作内存(Local Memory)

解决共享对象可见性的问题:volatile
它该如何学习
JMM是一个抽象的概念,理论
可见性
volatile关键字
指令重排
关于主内存与工作内存之间的具体交互协议,即一个变量如何从主内存拷贝到工作内存、如何从工作内存同步到主内存之间的实现细节,Java内存模型定义了以下八种操作来完成:
Java内存模型还规定了在执行上述八种基本操作时,必须满足如下规则:
以上就是【Bug 终结者】对 【高级篇】Java JVM实战 之 内存调优 的简单介绍,JVM 内存优化,偏底层知识,认真研究,虚心进步,加油,走过的艰难终将铺向成功的道路,学习JVM可了解Java程序的运行方式以及运行原理,更深层次的理解可提高自己对Java知识再上高峰,JVM 内存调优,进阶必备!
如果这篇【文章】有帮助到你,希望可以给【Bug 终结者】点个赞👍,创作不易,如果有对【后端技术】、【前端领域】感兴趣的小可爱,也欢迎关注❤️❤️❤️ 【Bug 终结者】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💝💝💝!