是否有任何实用程序允许我获取 .class 文件并将其转换为 jvm 字节码?
有一个关于类反编译的问题,我不想要这个,我想要反汇编。从航站楼。
我只找到 GUI 项目。 https://github.com/java-decompiler/jd-gui 我只想要一个简单的实用程序
给定一个 .class 对象,有一些工具可以帮助您分解它。 其中之一是
javap
,它与 JDK
一起使用 -c
标志,让我们看看它的实际效果。
$ javap -c Hello.class
Compiled from "Hello.java"
public class Hello {
public Hello();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String Hello, world!
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}
现在一切都很好,除了它是只读的,这使得编辑变得困难,但是由于这是官方的反汇编器,所以它是一个很好的参考。 jasmin 还有另一个反汇编器,它是一个 java 汇编器,有点过时,用 C++ 编写,适用于 Windows。假设您有一个 C++ 编译器(例如从 msys2 分发的编译器),这个编译器不需要 JRE。
git clone https://github.com/masakioba/jhoja.git
cd jhoja
g++ jhoja.cpp -fpermissive -o jhoja.exe
我们可以尝试
$ ./jhoja.exe /z/jvmstuff/Hello.class
;/* Class file Z:/jvmstuff/Hello.class version 50.0 */
.source Hello.java
.class public synchronized Hello
.super java/lang/Object
.method public <init>()V
.limit stack 1
.limit locals 1
aload_0
invokespecial java/lang/Object/<init>()V
return
.end method
.method public static main([Ljava/lang/String;)V
.limit stack 2
.limit locals 1
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "Hello, world!"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
return
.end method
这又可以让您使用 jasmin 将其组装回来。
还有一个,其实有很多
jasm
程序,不过这个需要JRE 17才能运行,你可以这样打包到本地
# Check if ~/.local/bin and ~/.local/share/java exist, and create them if not
mkdir -p ~/.local/bin ~/.local/share/java
# Check if ~/.local/bin is in PATH
if ! echo "$PATH" | grep -q ":.*/\.local/bin"; then
# Append ~/.local/bin to .bashrc
echo 'export PATH="$PATH:$HOME/.local/bin"' >> ~/.bashrc
# Append ~/.local/bin to the current PATH
export PATH="$PATH:$HOME/.local/bin"
fi
# Download jasm-cli-2.4.0-all.jar
wget -O ~/.local/share/java/jasm-cli-2.4.0-all.jar https://github.com/jumanji144/Jasm/releases/download/2.4.0/jasm-cli-2.4.0-all.jar
# Create the jasm script
cat > ~/.local/bin/jasm << 'EOF'
#!/bin/bash
java -jar ~/.local/share/java/jasm-cli-2.4.0-all.jar "$@"
EOF
chmod +x ~/.local/bin/jasm
# Test the jasm script
jasm --version
并测试输出
$ jasm decompile /z/jvmstuff/Hello.class
.super java/lang/Object
.class public super Hello {
.method public <init> ()V {
parameters: { this },
code: {
A:
aload this
invokespecial java/lang/Object.<init> ()V
return
}
}
.method public static main ([Ljava/lang/String;)V {
parameters: { p0 },
code: {
A:
getstatic java/lang/System.out Ljava/io/PrintStream;
ldc "Hello, world!"
invokevirtual java/io/PrintStream.println (Ljava/lang/String;)V
B:
return
}
}
}
可能还有其他方法,但这些只是我发现的一些方法,第二个和第三个都可以让你将其转换为字节码,第三个包括汇编器和反汇编器,第二个你需要单独获取 jasmin。之所以有如此多的汇编程序是因为Sun/Oracle从来没有太多官方的汇编程序。