JVM优化实战

JVM调优实战指南:从原理到落地的全面优化方案 JVM调优的本质是"平衡内存、GC与业务需求的艺术"。它不需要死记硬背参数,而需要理解JVM内存模型与GC机制,结合工具定位问题,通过数据验证效果。大多数应用的性能问题,80%源于代码,20%源于JVM配置。在调优JVM之前,先审视代码是否还有优化空间——这往往是投入产出比最高的选择。最后,调优是一个持续迭代的过程,随着业务增长与数据量变化,需定期重新评估JVM配置,让应用始终运行在最佳状态。 阅读详情

1 GC相关内存

1.1 内存划分

1.1.1 堆(Heap)

存放 new MyClass() 的对象,是GC的主要区域,
-Xms / -Xmx 分别是堆的初始容量、最大可扩展容量,建议初始值设置为最大值,以免反复扩展或缩减的开销;

  • 新生代(Young Generation):又划分为 Eden(伊甸园,新生区), Survivor#0(幸存区S0), Survivor#1(幸存区S1)

  • 老年代(Tenured Generation)

-XX:NewRatio 是“老年代 / 新生代”的比例,默认值为 2;
-XX:SurvivorRatio 是指 Eden/Survivor#0 的比例,而Survivor#0 与 Survivor#1 容量相同;

1.1.2 永久代(Permanent Generation)

存放类信息、常量、大对象(比如 new byte[n]对象);
-XX:PermSize / -XX:MaxPermSize 为永久代的初始、最大容量,建议初始容量指定为最大容量;
JDK8 中,永久代被完全的移除了,包括相关参数 -XX:PermSize / -XX:MaxPermSize。改用 Metaspace,通过参数-XX:MetaspaceSize / -XX:MaxMetaspaceSize / -XX:CompressedClassSpaceSize 设定;

1.1.3 实例解析

选项 -Xms300M -Xmx300M -XX:NewRatio=2 -XX:SurvivorRatio=8 -XX:PermSize=100M -XX:MaxPermSize=100M 含义为:

  • 永久代固定尺寸为 100M;

  • 整个堆固定尺寸为 300M,其中“老年代 / 新生代”为-XX:NewRatio=2,所以老年代为 200M,新生代为 100M;

  • 新生代总共 100M,其中“Eden / Survivor0”为-XX:SurvivorRatio=8,所以 Eden 为 80M,Survivor0=Survivor1=10M。
    官方资料:http://www.oracle.com/technetwork/articles/java/vmoptions-jsp-140102.html

1.2 JVM内存分配策略

1.2.1. 对象优先分配在 Eden

首先尝试在 Eden 分配,若 Eden 空间不足,就发起 YoungGC(简称YGC);

  • 如果幸存对象(被根对象直接或间接引用)在 SurvivorTo 能放下,则存活对象全部移入 SurvivorTo;

  • 如果幸存对象在 SurvivorTo 存放不下,则存活对象全部移入老年代;
    如果此时老年代空间不足,则发起一次 FullGC(简称FYC,整个系统停顿,老年代也参与回收);
    如果 FullGC 时空间仍然周转不过来,则报 OutOfMemoryError 并导致进程结束;

  • 如果YGC/FGC能周转过来,则新对象分配在 Eden 中;

1.2.2. 大对象直接分配在老年代

所谓的大对象是指,需要大量连续内存的 Java 对象,尤其是长字符串或数组,比如 byte[n] 对象;
可以指定多大才算大对象(只对 Serial/ParNew 有效);

1.2.3. 长期存活对象移入老年代

经历 n 次 YGC 仍然存活的对象,下次 YGC 时将被移入老年代;
可以设置该数值:-XX:MaxTenuringThreshold=15(默认)

1.2.4. 永久代满了也会导致 FullGC

老年代、永久代的垃圾收集是捆绑在一起的,因此无论两者谁满了,都会触发两者的FullGC。

1.2.5. 动态对象年龄判定

如果 Survivor 相同年龄对象占用空间达到一半,则大于等于该年龄的对象都移入老年代;

1.2.6. 冒险模式

JDK 6u24 之后,总是开启冒险模式(先尝试 YGC,以免 FGC 频繁);
每次 YGC 之前,如果老年代最大连续空间,大于新生代所有对象空间之和,则 YGC 肯定成功,否则:

  • 如果老年代最大连续空间,大于历次晋升老年代的平均值,则先冒险尝试 YGC;

  • 如果老年代最大连续空间,小于历次晋升老年代的平均值,则直接 FullGC;

2 JVM优化原则

2.1 优化目标

2.1.1 尽量减少 YoungGC,以减少代码停顿

2.1.2 尽量减少 FullGC,以减少系统停顿

一天最多 FullGC 一次,最好在系统空闲期(如深夜);

2.2 优化方法

2.2.1 代码角度

缩短对象生命期,尤其是大对象

2.2.2 JVM参数角度

优化JVM参数以减少YGC/FGC次数,可替换收集器

3 服务端开启 JMX/jstatd

这两项功能必须开启,下面的可视化工具 VisualVM 要用到。

3.1 设置系统环境变量

### 下文多处用到此变量,统一维护在系统环境变量里
set JMX_HOSTNAME=192.168.214.128 ## Windows
export JMX_HOSTNAME=192.168.214.128 ## Linux

3.2 开启 JMX(指定端口 1090)

需要注意的是,如果服务端 JMX 开启了修改和控制权限,此时如果不验证监控客户端的身份,那么所有用户都可以修改和控制 Tomcat 服务,所以重要的服务器应该开启用户名和密码验证。

3.2.1 准备用户验证文件

### Windows
copy/b "%JAVA_HOME%\jre\lib\management\jmxremote.password.template" "%CATALINA_BASE%\conf\jmxremote.password"
copy/b "%JAVA_HOME%\jre\lib\management\jmxremote.access" "%CATALINA_BASE%\conf\jmxremote.access"

### Linux
cp "$JAVA_HOME/jre/lib/management/jmxremote.password.template" "$CATALINA_BASE/conf/jmxremote.password"
cp "$JAVA_HOME/jre/lib/management/jmxremote.access" "$CATALINA_BASE/conf/jmxremote.access"

jmxremote.password 用于设置各个【用户名|密码】

### $CATALINA_BASE/conf/jmxremote.password
jmxadmin    jmxpwd

jmxremote.access 用于设置各个【用户名|权限】

### $CATALINA_BASE/conf/jmxremote.access
jmxadmin    readwrite \
            create javax.management.monitor.*,javax.management.timer.* \
            unregister

3.2.2 修改用户验证文件权限

安全起见,JMX 限制其他用户不可读这两个用户验证文件。
默认情况下,Windows/Linux 下分别会报如下错误:

  • 错误: 必须限制口令文件读取访问权限: %CATALINA_BASE%\conf\jmxremote.password

  • Error: Password file read access must be restricted: $CATALINA_BASE/conf/jmxremote.password

Windows下可按如下操作修改文件权限:

  • 右键单击文件 jmxremote.password,弹出菜单中选“属性”,再点“安全”/“高级”/“更改权限”/“包括可从该对象的父项继承的权限”(弹出窗口中选“删除”以删除所有访问权限);

  • 再选“添加”/“高级”/“立即查找”,选中你的用户(如 WKF-PC),点“确定”;

  • 权限项目窗口中勾选“完全控制”,点“确定”。

Linux 下则更简单:

cd $CATALINA_BASE/confchmod 600 jmxremote.password jmxremote.access

3.2.3 修改 Tomcat 启动时 JVM 选项

如果测试服务器无需开启用户验证,只需修改下面参数 authenticate=false, 并去掉 password.file 和 access.file 两个参数。

### Windows: %CATALINA_HOME%\bin\startup.bat
set JAVA_OPTS=%JAVA_OPTS% -Djava.rmi.server.hostname=%JMX_HOSTNAME% ^
    -Dcom.sun.management.jmxremote=true ^
    -Dcom.sun.management.jmxremote.port=1090 ^
    -Dcom.sun.management.jmxremote.ssl=false ^
    -Dcom.sun.management.jmxremote.authenticate=true ^
    -Dcom.sun.management.jmxremote.password.file=%CATALINA_BASE%\conf\jmxremote.password ^
    -Dcom.sun.management.jmxremote.access.file=%CATALINA_BASE%\conf\jmxremote.access
    
### Linux: $CATALINA_HOME/bin/startup.sh
export JAVA_OPTS="$JAVA_OPTS -Djava.rmi.server.hostname=$JMX_HOSTNAME
    -Dcom.sun.management.jmxremote=true-Dcom.sun.management.jmxremote.port=1090
    -Dcom.sun.management.jmxremote.ssl=false
    -Dcom.sun.management.jmxremote.authenticate=true
    -Dcom.sun.management.jmxremote.password.file=$CATALINA_BASE/conf/jmxremote.password
    -Dcom.sun.management.jmxremote.access.file=$CATALINA_BASE/conf/jmxremote.access"

3.3 开启 jstatd agent(默认端口 1099)

### $CATALINA_BASE/conf/jstatd.policy
### 可借鉴 $JAVA_HOME/jre/lib/security/java.policy
grant codeBase "file:${java.home}/../lib/tools.jar" {
    permission java.security.AllPermission;
};
### $CATALINA_HOME/bin/jstatd.sh
### chmod +x $CATALINA_HOME/bin/jstatd.sh
#!/bin/sh

PID=`jps | grep Jstatd | awk '{print $1}'`
if [ -n "$PID" ]; then
    echo "kill -9 $PID ..."
    kill -9 $PID
fi

jstatd -J-Djava.rmi.server.hostname=$JMX_HOSTNAME \
-J-Djava.security.policy=$CATALINA_BASE/conf/jstatd.policy \
-J-Xms128M -J-Xmx128M -J-XX:NewRatio=1 -J-XX:SurvivorRatio=8 -J-XX:PermSize=16M -J-XX:MaxPermSize=16M \
< /dev/null &> $CATALINA_BASE/logs/jstatd.log &

 

 

 

3.4 配置防火墙(放行端口 1090/1099)

### /etc/sysconfig/iptables
-A INPUT -m state --state NEW -m tcp -p tcp --dport 1090 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 1099 -j ACCEPT
### 重启生效: systemctl restart iptables

4 可视化工具

4.1 JConsole

早期的 Java 故障和监控工具,现在可以由强大的 VisualVM 代替。

4.2 VisualVM

4.2.1 文档

http://m.blog.youkuaiyun.com/article/details?id=51090115
http://docs.oracle.com/javase/8/docs/technotes/guides/visualvm/index.html

4.2.2 下载与安装

可以使用 JDK 自带的 %JAVA_HOME%\bin\jvisualvm.exe;
也可以使用最新版本,下载方法如下:
下载页:https://visualvm.github.io/download.html
主程序:https://github.com/visualvm/visualvm.src/releases/download/1.3.9/visualvm_139.zip
汉化包:https://github.com/visualvm/visualvm.src/releases/download/1.3.9/visualvm_139-ml.zip
IDE插件:https://visualvm.github.io/idesupport.html
主程序与汉化包解压到同一目录,最终主程序为 bin\visualvm.exe;
IDE插件支持 Eclipse/IntelliJ IDEA,可以随着 IDE 启动。

4.2.3 安装 VisualGC 插件

http://www.oracle.com/technetwork/java/visualgc-136680.html
VisualVM 中,点击菜单“工具”/“插件”,如下图安装:

有些插件不能成功安装,可下载 nbm 包再手工安装:
https://visualvm.github.io/plugins.html
http://visualvm.java.net/pluginscenters.html
或者在插件设置里,修改或新增插件源(pluginscenters.html里点击后能找到),再安装。
http://bits.netbeans.org/VisualVM/uc/release138/updates.xml
http://bits.netbeans.org/VisualVM/uc/8u40/updates.xml
几款有用的插件:

  • BTrace Workbench(只适用于本地应用): 用于不停止进程的情况下添加代码跟踪,入口在应用的右键菜单里;

  • KillApplication(只适用于本地应用): 用于杀掉进程,入口在应用的右键菜单里;

  • VisualVM-MBeans(本地和远程通用):类似于 JConsole 展示应用的 MBean,包括值、操作、通知等;

  • Tracer(本地和远程通用): 以时间曲线图展示多种指标,包括CPU/GC/Heap/PermGen/Classes/Threads等。

4.2.4 前提条件

对于本地应用,VisualVM 所有功能直接支持它;
对于远程应用,VisualGC 标签页要求服务端开启 jstatd agent,其他标签页要求开启 JMX,否则会显示错误“不受此 JVM 支持”。
对于远程应用,需要注意的是,服务端 jstatd/JMX 重启后,VisualVM 必须重启或者重建 JMX 连接,否则服务端调整在 VisualVM 中不生效。

4.2.5 添加远程主机 / JMX连接

(1)添加“远程主机”,指定远程服务器的 IP 和 jstatd 端口:

(2)添加“JMX 连接”,指定远程应用的 JMX 端口、用户名和密码:

4.2.6 监控远程应用

(1)双击左侧的“JMX 连接”(注意小图标底部有 JMX 字样),切换至“概述”标签页,可看到概述和 JVM 参数信息:

(2)切换至“监视”标签页,可看到 CPU、Heap、Class加载、线程等时间曲线图:

(3)切换至“线程”标签页,可看到各线程 CPU 耗时统计:

(4)切换至“抽样器”标签页,可看到热点方法耗时、主要对象占用空间统计(可用于定位内存泄露):

(5)切换至“VisualGC”标签页,可看到各种内存变化曲线、各GC时间点(可用于JVM参数调优):

4.2.7 JVM 优化实战

(1)优化前,没有明确指定各内存大小,使用 Java 默认内存大小,相当于指定为:

export JAVA_OPTS="$JAVA_OPTS -Xms52M -Xmx244M -XX:NewRatio=2-XX:SurvivorRatio=8 -XX:PermSize=30M -XX:MaxPermSize=1G"

可见 YoungGC 很频繁:


观察图形可得出以下优化方案:

  • 机器内存为 1G,本应用为系统唯一大应用,分给它 512M,另外 512M 预留给系统和其他应用;

  • 永久代只需 30M,可指定初始和最大值为 64M,避免反复伸缩的开销;

  • 整个堆(新生代+老年代)目前内存为 240M,可增加至 384M,指定初始和最大值都为 384M,避免反复伸缩的开销;

  • YoungGC 过于频繁,原因是 Eden 区过小。“老年代/新生代”目前比例为 -XX:NewRatio=2,看图形可知,老年代中长寿对象并不多,可缩减老年代让给新生代,所以调整 -XX:NewRatio=1;

  • “Eden / Survivor0”比值目前为 -XX:SurvivorRatio=8,暂不调整。

(2)优化后,指定 JVM 选项为:

### Linux: $CATALINA_HOME/bin/startup.shexport JAVA_OPTS="$JAVA_OPTS -Xms384M -Xmx384M 
-XX:NewRatio=1-XX:SurvivorRatio=8 -XX:PermSize=64M -XX:MaxPermSize=64M"

可见 YoungGC 大幅减少:

(3)优化前后对比:
优化前:YoungGC 102次,总耗时 965ms, FullGC 5次,总耗时 240ms,而且应用稳定后 YoungGC 仍然反复发生;
优化后:YoungGC 3次,总耗时 26ms, FullGC 1次,总耗时 4ms,而且应用稳定后 YoungGC 长期未再发生;
优化效果非常明显。

5 命令行工具(服务端)

5.1 jps(查看Java进程)

### jps -vlm | grep Bootstrap
1162 ## 进程ID
    -Xms300M -Xmx300M -XX:NewRatio=2 -XX:SurvivorRatio=8 ## -v的作用,显示 JVM 参数
    org.apache.catalina.startup.Bootstrap ## -l的作用,显示主类的全名(或JAR包路径)
    start ## -m 的作用,显示传递给主类 main() 函数的参数

5.2 jmap/jhat(快照的生成与查看)

### 服务器上执行,生成 heapdump 快照文件
jmap -dump:live,format=b,file=tomcat.hprof 1162
sz tomcat.hprof ## 下载到个人PC

### 创建WEB服务,个人PC上可以用浏览器查看 http://localhost:8080/
### 功能较弱,以 package 分组展示,“Show heap histogram”可用于分析内存泄露。
### 也可以用 VisualVM 打开快照文件来查看
jhat -port 8080 tomcat.hprof

### jmap 更多功能
jmap -heap 1162 ## 查看堆内存划分、各区块尺寸、已用容量和比率等
jmap -histo:live 1162 ## 可用于排查内存泄露,查看堆中(仅存活的)各 class 的实例数、总占用空间

5.3 jstack

jstack 1162 > jstack.log ## 可生成应用的各线程 StackTrace

5.4 jcmd

jcmd ## 类似于 jps,查看 java 进程
jcmd 1162 help ## 查看该进程支持的命令
jcmd 1162 VM.uptime ## 显示启动时间
jcmd 1162 VM.flags ## 显示VM标志
jcmd 1162 VM.version ## 查看虚拟机版本
jcmd 1162 VM.command_line ## 显示命令行及参数
jcmd 1162 VM.system_properties ## 显示系统属性
jcmd 1162 GC.run ## 执行 System.gc()
jcmd 1162 GC.run_finalization ## 执行 System.runFinalization()
jcmd 1162 GC.class_histogram ## 相当于 jmap -histo:live 1162
jcmd 1162 GC.heap_dump tomcat.hprof ## 生成堆快照文件
jcmd 1162 Thread.print ## 相当于 jstack 1162
jcmd 1162 PerfCounter.print ## 显示进程内各种计数器

6 开发监控系统

假设有个需求(这里只是为了演示,现实中不会这么简单粗暴,现实中还需要限制在凌晨才触发):Heap 使用率高于 60%,就要求强制 FullGC。

6.1 Shell 脚本

PID=`jps | grep Bootstrap | awk '{print $1}'`

## 计算 Heap 使用率
## 下面命令会输出 Eden/S0/S1/Tenured 各自的总空间和已用空间,很容易算出 Heap 使用率:
## used(Eden+S0+S1+Tenured)/total(Eden+S0+S1+Tenured)# jstat -gc $PID
## 判断使用率大于 60% 才执行 FullGCjcmd $PID GC.run
 

6.2 Java 代码

代码中使用的“java.lang:type=Memory”、“HeapMemoryUsage”可以借助 VisualVM/MBeans插件的 Attribtes/Operations 标签页中找到,如下图:

package wang.kefeng.JmxAdmin;
import java.lang.management.MemoryUsage;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * @author http://kefeng.wang
 * @date 2016-11-24 20:20:08
 */
public class App {
    private static final String JMX_HOSTNAME = "192.168.214.128:1090";
    private static final String JMX_USERNAME = "jmxadmin";
    private static final String JMX_PASSWORD = "jmxpwd";
    private static final Logger logger = LoggerFactory.getLogger(App.class);
    public static void main(String[] args) throws Exception {
        // 1.建立连接(mbsc)
        String jmxURL = "service:jmx:rmi:///jndi/rmi://" + JMX_HOSTNAME + "/jmxrmi";
        JMXServiceURL serviceURL = new JMXServiceURL(jmxURL);
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("jmx.remote.credentials", new String[] { JMX_USERNAME, JMX_PASSWORD });
        JMXConnector connector = JMXConnectorFactory.connect(serviceURL, map);
        MBeanServerConnection mbsc = connector.getMBeanServerConnection();
        // 2.获取远程应用数据
        ObjectName objectName = new ObjectName("java.lang:type=Memory");
        Object heapMemoryUsage = mbsc.getAttribute(objectName, "HeapMemoryUsage");
        MemoryUsage usage = MemoryUsage.from((CompositeDataSupport) heapMemoryUsage);
        // 示例:如果 Heap 使用率大于 60%,则请求 FullGC
        long usedRate = usage.getUsed() * 100 / usage.getMax();
        logger.info("usedRate={}, {} / {}", usedRate, usage.getUsed(), usage.getMax());
        if (usedRate > 30) {
            mbsc.invoke(objectName, "gc", null, null);
            logger.info("gc() OK.");
        }
        // 3.更多有用的 MBeans
        // (1)com.sun.management:type=HotSpotDiagnostic
        // dumpHeap(), getVMOption(), setVMOption()
        // (2)java.util.logging:type=Logging
        // getLoggerLevel(), setLoggerLevel()
    }
}

 

7 内存泄露插件

7.1 内存泄露现象

老年代越来越大,GC越来越频繁、执行时间越来越长,而且GC后内存未释放。

7.2 生成快照文件(hprof Heap信息文件)

  • 使用Java的jmap命令来生成;

  • 通过JMX的MBean用Java代码生成;

7.3 分析dump文件

  • 最佳方案是使用 Eclipse MAT 插件;

  • 其他候选方案:Java 自带工具 Visual VM / jhat、IBM HeapAnalyzer;

7.4 分析内存泄漏

可看到可疑的内存泄露对象,看到占用空间大的对象及其调用关系。

8 GC日志

8.1 开启gc日志文件

### Linux: $CATALINA_HOME/bin/startup.sh
export JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDateStamps -XX:+PrintGCDetails
-XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -Xloggc:$CATALINA_BASE/logs/gc.log"


[停顿类型8.2 日志文件格式解析

  [新生代: GC前本区域已用容量 -> GC后本区域已用容量 (本区域总容量), 本区域GC耗时]
  [老年代: GC前本区域已用容量 -> GC后本区域已用容量 (本区域总容量), 本区域GC耗时]
    GC前Heap已用容量 -> GC后Heap已用容量 (Heap总容量)
  [永久代: GC前本区域已用容量 -> GC后本区域已用容量 (本区域总容量), 本区域GC耗时]
  [Times: 用户耗时=xx 系统耗时=yy, 实际耗时=zz secs]

==== server 模式的 GC+FullGC ====
新生代:PSYoungGen=Parallel Scavenge
老年代:ParOldGen=Parallel Old
永久代:PSPermGen

[GC
    [PSYoungGen: 6980K->600K(9216K)]
    6980K->6744K(19456K), 0.0028901 secs]
    [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC
    [PSYoungGen: 600K->0K(9216K)]
    [ParOldGen: 6144K->6617K(10240K)]
    6744K->6617K(19456K)
    [PSPermGen: 2567K->2566K(21504K)], 0.0095238 secs]
    [Times: user=0.02 sys=0.00, real=0.02 secs]

 

 

 

==== client 模式的 GC+FullGC ====
新生代:DefNew=Serial(Default New Generation)
老年代:Tenured
永久代:Perm

[GC
    [DefNew: 6871K->382K(9216K), 0.0037941 secs]
    [Tenured: 6144K->6525K(10240K), 0.0033262 secs]
    6871K->6525K(19456K),
    [Perm : 186K->186K(12288K)], 0.0081090 secs]
    [Times: user=0.00 sys=0.00, real=0.00 secs]

[Full GC
    [Tenured: 6525K->6514K(10240K), 0.0026225 secs]
    6525K->6514K(19456K),
    [Perm : 186K->186K(12288K)], 0.0028221 secs]
    [Times: user=0.00 sys=0.00, real=0.00 secs]

 

 

 

=================================

8.3 gc.log 解析工具

8.3.1 在线分析

http://gceasy.io/

8.3.2 ga456(IBM)

https://www.ibm.com/developerworks/community/alphaworks/tech/pmat
ftp://public.dhe.ibm.com/software/websphere/appserv/support/tools/pmat/ga456.jar

8.3.3 HPjmeter

https://h20392.www2.hpe.com/portal/swdepot/displayProductInfo.do?productNumber=HPJMETERSW
需要注册帐号并登录,最终下载页中选择“Use Standard Download”,Windows上可下载这两个:
MS Windows XP/Vista/7 HPjmeter 4.4.00.00 Console - Oct 2014 (Z7550-01611_hpjmeter_console_4.4.00.00_windows_setup.exe)
HPjmeter 4.4.00.00 Console jar file zip format - Feb 2015 (Z7550-63266_hpjmeter_4.4.00.00.zip)

8.3.4 GCViewer

http://www.tagtraum.com/gcviewer.html
http://www.tagtraum.com/gcviewer-download.html
http://www.tagtraum.com/download/gcviewer-1.29-bin.zip

8.3.5 IBM GCMV(Eclipse 插件)

GCMV=Garbage Collection and Memory Visualizer
插件中心搜索 “GCMV” 来安装,然后在菜单中打开: Window / Perspective / Open Perspective / GCMV

8.3.6 gchisto(VisualVM 插件)

https://gchisto.dev.java.net/
http://java.net/projects/gchisto
http://pietrowski.info/wp-content/uploads/2009/06/GCHisto.tgz

8.3.7 其他更多

https://code.google.com/archive/p/gclogviewer/
https://code.google.com/archive/p/verbosegcanalyzer
http://fasterj.com/tools/gcloganalysers.shtml
http://techblog.netflix.com/2013/05/garbage-collection-visualization.html

 

性能优化实战:从火焰图分析到JVM调优 火焰图分析和JVM调优是性能优化的两个重要方面。通过火焰图,开发者可以快速定位性能瓶颈;通过JVM调优,可以显著提升Java应用的性能和稳定性。在实际项目中,建议结合具体业务需求和系统环境,采取综合的性能优化策略,并持续监控和分析系统性能,以确保应用的高效运行。通过本文的实战分析,希望开发者能够更深入地了解火焰图分析和JVM调优的技巧和方法,为应用的性能优化提供有力的支持。 阅读详情

相关推荐

【基础+实战】JVM原理及优化系列之八:如何查看JVM参数配置?

1. 查看JAVA版本信息 2. 查看JVM运行模式  在$JAVA_HOME/jre/bin下有client和server两个目录,分别代表JVM的两种运行模式。   client运行模式,针对桌面应用,加载速度比server模式快10%,而运行速度为server模式的10分之一。client下默认的堆容量 -Xms1M -Xmx64M   server运行模式,针对服务器应用。serv...

行者无疆 1906

java的jvm调优相关工具——jvm调优、GC、压测、linux命令

jmap jdk自带命令。jmap是一个多功能的命令,查看JVM内存使用情况。它可以生成 java 程序的 dump 文件, 也可以查看堆内对象示例的统计信息、查看 ClassLoader 的信息以及 finalizer 队列。 jmap -dump:live,format=b,file=myjmapfile.txt 19570 jstack jdk自带命令。查看运行java程序的java stack和native stack的信息。 jstack pid jstat jdk自带命令。可以

透明大脑 1352

hpjmeter4.5.rar

hpjmeter jvm分析,gc分析

gc日志分析工具

性能测试排查定位问题,分析调优过程中,会遇到要分析gc日志,人肉分析gc日志有时比较困难,相关图形化或命令行工具可以有效地帮助辅助分析。 Gc日志参数 通过在tomcat启动脚本中添加相关参数生成gc日志 -verbose.gc开关可显示GC的操作内容。打开它,可以显示最忙和最空闲收集行为发生的时间、收集前后的内存大小、收集需要的时间等。 打开-xx:+ printGC...

系统运维 918

hpjmeter jvm gc监控工具

hpjmeter jar 包,下载 hpjmeter 监控应用程序,只需要下载后放到根目录,java -jar hpjmeter.jar 即可

hpjmeter安装包下载

压力测试工具,对webhttp请求,数据库并发访问

成为JavaGC专家Part II — 如何监控Java垃圾回收机制

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33892359的博客 177

HPjmeter 4.4.00.00 Console jar

HPjmeter 4.4.00.00 Console jar

JMeter下载及安装(附插件及中文包超详细)

JMeter下载及安装(附插件及中文包超详细)

cv_dashi的博客 6万+

jmeter2024年最新版

更好的可扩展性:随着Web应用程序和技术的不断发展,性能测试的需求也日益复杂。JMeter 2024版提供了更好的可扩展性,允许用户通过插件和自定义组件来扩展其功能,以满足不断变化的性能测试需求。 支持多种协议和测试类型:JMeter最初是为Web应用程序的负载测试而设计的,但现在已经扩展到支持多种协议和技术。在2024版中,JMeter进一步改进了对非Web应用程序的性能测试的支持,包括数据库、消息队列、RESTful服务等。 更高效的性能测试:随着硬件和技术的进步,性能测试的规模和复杂性也在增加。JMeter 2024版引入了更高效的测试引擎和数据处理能力,可以更快地生成和处理大量的测试数据。

长短期记忆网络(Long Short-Term Memory networks, LSTM)

如何简单的理解LSTM——其实没有那么复杂:

weixin_39910711的博客 2万+

JVM 调试与内存优化实战详解

在微服务与云原生架构盛行的当下,Java 应用常面临高并发、高可用与大数据量处理的挑战。JVM(Java Virtual Machine)作为 Java 程序运行的基石,其性能直接影响系统的稳定性与吞吐能力。本文将从 JVM 内存模型入手,结合真实生产环境中的常见内存问题与排查流程,深入剖析调试工具与优化手段,帮助开发者构建高性能、低延迟的 Java 服务。🚀监控为先:实时 GC/内存/线程报警与可视化日志为证:规范 GC 日志,定期归档分析快照为王:关键时刻堆 & 线程快照 + 深度剖析策略为纲。

weixin_44876263的博客 1674

opencv+nvcodec实现视频硬解码

最近遇到一个新项目,AI推理在上,为了方便和节省成本的考虑决定研究下模块。根据官网的说法显卡具有独立的和模块,所以理论上和是独立互不干涉的。以前的项目都只是把显卡当成推理工具,没有将它的功能利用起来,本身也是一种浪费。事实真的有这么丝滑吗?看到这里,如果你真的觉得是白叫的那就真的是了,事实究竟如何,请听我娓娓道来。NVCODEC全称是 NVIDIA VIDEO CODEC,是NVIDIA为绝大多数显卡配置的硬件编解码单元。不一定是所有显卡都有,一般来讲越新的显卡硬件编解码就越强,支持的格式也就越新。

jiexijihe945的博客 1万+

JVM实战—10.MAT的使用和JVM优化总结

在JDK 1.6时:"Hello World"这个字符串底层是基于一个数组来存放那些字符的,比如[H,e,l,l,o,,W,o,r,l,d]这样的数组,然后切割出来的"Hello"字符串它不会对应一个新的数组,而是直接映射到原来那个字符串的数组,采用偏移量表明自己是对应原始数组中的哪些元素,比如"Hello"可能对应[H,e,l,l,o,W,o,r,l,d]数组中0~4位置的元素。在接下来的一个步骤,务必要注意:如果是线上导出来的dump内存快照,很多时候可能都是几个G的。

weixin_55010563的博客 679

博途PLC PID仿真LSim_PT1库算法(一阶系统差分方程推导全过程)

博途PLC的PID仿真可以参看下面这篇博客,这篇文章我们主要论坛仿真库LSim的算法由来。如何利用博途PLC PID_Compact 进行PID仿真(一阶系统)_RXXW_Dor的博客-优快云博客博途PLC PID控制器 PID_Compact FB如何使用可以参看下面这篇文章,这里不再赘述。

RXXW_Dor的博客 2858

手把手教你学Simulink--基于车联网与智能交通系统的场景实例:基于车联网(V2X)的实时路况信息共享与处理

《基于Simulink的车联网(V2X)实时路况共享系统仿真》摘要:本文详细介绍使用Simulink构建V2X智能交通系统的完整方法。系统包含交通路网建模、V2X通信实现(支持DSRC/C-V2X标准)、多源路况信息融合、动态路径规划等核心模块。通过对比实验,验证V2X可使平均车速提升52%,行程时间缩短34%,显著提升交通效率。文章还探讨了AI预测调度、车辆编队等高级应用,为智慧交通系统开发提供实用参考。所需工具包括Simulink、SimEvents及无线通信工具箱等。

MHD0815的博客 737

JVM调优实战 Day 13:微服务架构中的JVM优化

微服务架构中JVM的隔离性和资源分配特点JVM参数设置对微服务性能的关键影响GC策略选择与调优方法线程池配置和类加载机制优化实际项目中的JVM调优案例分析常用JVM监控与诊断工具的使用。

在未来等你的专栏 1064

vue3 - vite报错TypeError: crypto.hash is not a function(vue3+vite启动运行提示错误,项目无法启动且打包报错失败,详细解决排查方案教程)

vue3 vite 报错,vue3+vite启动报错:TypeError: crypto.hash is not a function,创建vue3+vite项目时报错TypeError: crypto.hash is not a function,如何解决这个问题,VUE3+VITE报错crypto.hash,vue3运行报错,vite运行报错,vue3打包报错,vite打包报错,vue3新建项目无法运行,vue3 vite创建项目直接报错了,node版本不兼容,修改了node版本还是不行,依旧报错,一直

✅ 精选推荐文章 1万+

001、开篇词:JVM 优化实战

001、开篇词:JVM 优化实战,广大 Java 工程师心中永远的痛! 1、怎么统计FullGC的次 2、OOM内存溢出的模块?怎么模拟? 3、OO内存溢出定位步骤? 4、内存模型是怎么样的? 5、内存结构是怎么样的? 6、垃圾算法有那些? 7、类加载 8、垃圾回收 9、JVM参数优化 ...

longyi_java的专栏 480

YOLOv11改进 | 特殊场景改进篇 | 2024最新改进CPA-Enhancer链式思考网络(适用低照度、图像去雾、雨天、雪天)

本文给大家带来的改进机制是2024.3月份最新改进,由CPA-Enhancer: Chain-of-Thought Prompted Adaptive Enhancer for Object Detection under Unknown Degradations论文提出的CPA-Enhancer链式思考网络CPA-Enhancer通过引入链式思考提示机制,实现了对未知退化条件下图像的自适应增强。该方法的核心在于能够利用CoT提示对图像退化进行动态分析和适应,从而显著提升物体检测性能。

Snu77的博客 2013

PLC集群管理:C#上位机实现10台以上分布式PLC的集中监控与指令下发

本文介绍了一套基于C# WPF开发的PLC集群管理系统,用于解决现代工业自动化产线中分布式PLC监控难题。系统采用三层解耦架构,支持100台以内不同品牌PLC的集中管理,具备批量数据采集、指令下发、实时报警等功能。核心创新点包括:1)基于异步IO的连接池管理;2)统一通信接口设计;3)寄存器合并优化算法;4)三级优先级指令队列。实际应用表明,系统数据采集延迟低于100ms,指令下发成功率99.9%,有效解决了传统单PLC监控模式存在的效率低下问题。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 507

JVM实战(十一):Full GC导致频繁卡死的优化实战

` 2、

mingyuli的博客 3468

【实战项目开发技术分享】机器人安全通过狭窄区域的方案

在机器人的应用领域中,有时会遇到需要机器人通过狭窄区域的情况。无论是室内还是室外,机器人需要具备适应性和灵活性,以便在狭窄的空间中进行安全、高效的导航。本文将提供一些如何让机器人通过狭窄区域的实现方案和思路,希望帮助读者可以根据实际的开发需要进行适当调整和扩展。

xiewf的博客 2万+

JVM实战(13)——JVM优化概述

本章,我们先来对系统运行过程中可能会遇到的各种JVM性能问题作个概述,以此为引子,作为后续实战篇的铺垫。JVM性能优化其实就是针对JVM内存分配、参数设置进行优化,目的是减少GC次数,避免对象频繁进入老年代。所以,我们来先来回顾下新生代和老年代的垃圾回收过程,并看下可能会引发的各种JVM性能问题。

smart_an的专栏 1033

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

动手实战优化自己公司线上系统JVM,教程在这里!

Java性能调优都是老生常谈的问题,特别当“糙快猛”的开发模式大行其道时,随着系统访问量的增加、代码的臃肿,各种性能问题便会层出不穷。比如,下面这些典型的性能问题,你肯定或多或少都遇到过...

JAVA葵花宝典 243

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

JVM核心原理与实战优化指南

Java是一门跨平台、面向对象的高级编程语言,其核心优势在于“Write Once, Run Anywhere”。从Java语言本质切入,逐步深入JVM核心机制,兼顾不同背景学习者的认知梯度。掌握JVM,不仅为了面试通关,更是构建高并发、低延迟系统的核心竞争力!无论你是大学生还是资深工程师,学习JVM都至关重要。:多数对象朝生夕死(IBM研究:98%对象存活时间<1ms):JVM调优是理论与实践的结合,切忌盲目调整。:对象无法回收(如未关闭的连接)→。Java虚拟机(JVM)是。:泄漏积累或瞬时高负载。

搬砖的小熊猫的博客 1038

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

上一篇: 消息队列应用应用场景与技术选型(ActiveMQ、RabbitMQ、RocketMQ、Kafka)
下一篇: 分布式系统一致性(ACID、CAP、BASE、二段提交、三段提交、TCC、幂等性)原理详解
wrr-cat
博客等级 码龄9年 128粉丝 302原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值