一 点睛
jad:反编译,将字节码反编译成 java 源码
mc:内存编译器,编译 java 文件为字节码
redefine:加载外部的 字节码文件,替换 jvm 已加载的类,推荐使用 retransform 命令替换 redefine
classloader:将 JVM 中所有的classloader的信息统计出来,并可以展示继承树,urls等。
二 代码
package chapter03;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
public class JProfilerTest {
public static void main(String[] args) {
while (true){
ArrayList list = new ArrayList();
for (int i = 0; i < 500; i++) {
Data data = new Data();
list.add(data);
}
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Data{
private int size = 10;
private byte[] buffer = new byte[1024*1024]; // 1 mb
private String info = "hello,China";
}
三 windows下进入命令界面
D:\ProgramFiles\arthas-packaging-3.5.4-bin>jps
10656 Jps
12736 Launcher
2864
10668 JProfilerTest
D:\ProgramFiles\arthas-packaging-3.5.4-bin>as.bat 10668
环境变量 JAVA_TOOL_OPTIONS 没有定义
JAVA_HOME: D:\ProgramFiles\Java\jdk1.8.0_251
telnet port: 3658
http port: 8563
信息: 用提供的模式无法找到文件。
telnet wasn't found, please google how to install telnet under windows.
Try to visit http://127.0.0.1:8563 to connecto arthas server.
四 实战
# 反编译已加载的 String 类
[arthas@13768]$ jad java.lang.String
ClassLoader:
Location:
/*
* Decompiled with CFR.
*/
package java.lang;
import java.io.ObjectStreamField;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Formatter;
import java.util.Locale;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public final class String
implements Serializable,
Comparable<String>,
CharSequence {
private final char[] value;
private int hash;
private static final long serialVersionUID = -6849794470754667710L;
private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0];
public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();
public String(byte[] byArray, int n, int n2) {
/*545*/ String.checkBounds(byArray, n, n2);
/*546*/ this.value = StringCoding.decode(byArray, n, n2);
}
public String(byte[] byArray, Charset charset) {
/*515*/ this(byArray, 0, byArray.length, charset);
}
public String(byte[] byArray, String string) throws UnsupportedEncodingException {
/*491*/ this(byArray, 0, byArray.length, string);
}
public String(byte[] byArray, int n, int n2, Charset charset) {
/*460*/ if (charset == null) {
throw new NullPointerException("charset");
}
/*462*/ String.checkBounds(byArray, n, n2);
/*463*/ this.value = StringCoding.decode(charset, byArray, n, n2);
}
public String(byte[] byArray, int n, int n2, String string) throws UnsupportedEncodingException {
/*423*/ if (string == null) {
throw new NullPointerException("charsetName");
}
/*425*/ String.checkBounds(byArray, n, n2);
/*426*/ this.value = StringCoding.decode(string, byArray, n, n2);
}
String(char[] cArray, boolean bl) {
/*611*/ this.value = cArray;
}
public String(StringBuilder stringBuilder) {
/*600*/ this.value = Arrays.copyOf(stringBuilder.getValue(), stringBuilder.length());
}
......
}
# 反编译某个类中的某个具体方法
[arthas@13768]$ jad java.lang.String toString
ClassLoader:
Location:
@Override
public String toString() {
/*2887*/ return this;
}
# 反编译已加载的 chapter03.Data 类
[arthas@13768]$ jad chapter03.Data
ClassLoader:
+-sun.misc.Launcher$AppClassLoader@18b4aac2
+-sun.misc.Launcher$ExtClassLoader@17d9dda9
Location:
/E:/JVMDemo3/out/production/JVMDemo3/
/*
* Decompiled with CFR.
*/
package chapter03;
class Data {
private int size = 10;
private byte[] buffer = new byte[0x100000];
private String info = "hello,China";
Data() {
}
}
Affect(row-cnt:1) cost in 130 ms.
# 编译 HelloWorld.java 为 HelloWorld.class
[arthas@13768]$ mc E:/JVMDemo3/src/chapter03/HelloWorld.java
Memory compiler output:
E:\JVMDemo3\chapter03\HelloWorld.class
Affect(row-cnt:1) cost in 580 ms.
# 替换 JVM 中已加载的 HelloWorld.class
[arthas@13768]$ redefine E:\JVMDemo3\chapter03\HelloWorld.class
file does not exist, path:E:JVMDemo3chapter03HelloWorld.class
# JVM 中的类加载器
[arthas@13768]$ classloader
name numberOfInstances loadedCountTotal
com.taobao.arthas.agent.ArthasClassloader 1 2983
BootstrapClassLoader 1 2602
java.net.FactoryURLClassLoader 1 799
sun.misc.Launcher$ExtClassLoader 1 61
sun.misc.Launcher$AppClassLoader 1 8
sun.reflect.DelegatingClassLoader 2 2
Affect(row-cnt:6) cost in 6 ms.
# 以继承树的方式展示类加载器
[arthas@13768]$ classloader -t
+-BootstrapClassLoader
+-sun.misc.Launcher$ExtClassLoader@17d9dda9
+-com.taobao.arthas.agent.ArthasClassloader@449de647
+-sun.misc.Launcher$AppClassLoader@18b4aac2
+-java.net.FactoryURLClassLoader@75bcd85d
Affect(row-cnt:5) cost in 6 ms.
# 以列表的方式展示类加载器
[arthas@13768]$ classloader -l
name loadedCount hash parent
BootstrapClassLoader 2602 null null
com.taobao.arthas.agent.ArthasClassloader@449de647 2986 449de647 sun.misc.Launcher$ExtClassLoader@17d9dda9
java.net.FactoryURLClassLoader@75bcd85d 799 75bcd85d sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$AppClassLoader@18b4aac2 8 18b4aac2 sun.misc.Launcher$ExtClassLoader@17d9dda9
sun.misc.Launcher$ExtClassLoader@17d9dda9 61 17d9dda9 null
Affect(row-cnt:5) cost in 4 ms.
# 查看 AppClassLoader 实际的 urls
[arthas@13768]$ classloader -c 18b4aac2
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/charsets.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/deploy.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/ext/access-bridge-64.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/ext/cldrdata.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/ext/dnsns.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/ext/jaccess.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/ext/jfxrt.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/ext/localedata.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/ext/nashorn.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/ext/sunec.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/ext/sunjce_provider.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/ext/sunmscapi.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/ext/sunpkcs11.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/ext/zipfs.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/javaws.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/jce.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/jfr.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/jfxswt.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/jsse.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/management-agent.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/plugin.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/resources.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/rt.jar
file:/E:/JVMDemo3/out/production/JVMDemo3/
file:/D:/ProgramFiles/JetBrains/IDEA/lib/idea_rt.jar
file:/D:/ProgramFiles/arthas-packaging-3.5.4-bin/arthas-agent.jar
Affect(row-cnt:52) cost in 1 ms.