如何从命令提示符将.class文件分解为jvm字节码?

问题描述 投票:0回答:1

是否有任何实用程序允许我获取 .class 文件并将其转换为 jvm 字节码?

有一个关于类反编译的问题,我不想要这个,我想要反汇编。从航站楼。

我只找到 GUI 项目。 https://github.com/java-decompiler/jd-gui 我只想要一个简单的实用程序

terminal jvm
1个回答
0
投票

给定一个 .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从来没有太多官方的汇编程序。

© www.soinside.com 2019 - 2024. All rights reserved.