Swing实现反编译小工具

基于Swing 实现反编译 .class 文件和.jar文件,支持批量反编译,增加代码编辑和格式化功能,并支持反编译后文件导出保存。

具体功能点:

  • 打开 Class 文件:点击Open Class File按钮,选择要反编译的 .class 文件。反编译结果将显示在文本区域。
  • 打开 Jar 文件:点击Open Jar File按钮,选择要反编译的 .class 文件。反编译结果将显示在文本区域。
  • 保存反编译文件:点击Save Decompiled File按钮,选择保存位置,将反编译后的源代码保存到文件。

引入依赖

<dependencies>
    <dependency>
        <groupId>org.benf</groupId>
        <artifactId>cfr</artifactId>
        <version>0.151</version>
    </dependency>
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.9</version>
    </dependency>
</dependencies>

主框架类

package com.dzy.decompiler;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;

/**
 * 主框架类,包含反编译器的主要界面
 */
public class MainFrame extends JFrame {
    private JTextArea outputArea;
    private JButton openClassButton;
    private JButton openJarButton;
    private JButton saveButton;

    public MainFrame() {
        setTitle("Class File Decompiler");
        setSize(800, 600);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setMinimumSize(new Dimension(600, 400));

        initComponents();
        setLayout(new BorderLayout());

        add(new JScrollPane(outputArea), BorderLayout.CENTER);
        add(createButtonPanel(), BorderLayout.NORTH);
    }

    /**
     * 初始化组件
     */
    private void initComponents() {
        outputArea = new JTextArea();
        outputArea.setEditable(true);

        openClassButton = new JButton("Open Class File");
        openJarButton = new JButton("Open JAR File");
        saveButton = new JButton("Save Decompiled File");

        // 设置按钮动作监听器
        openClassButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JFileChooser fileChooser = new JFileChooser();
                fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
                int result = fileChooser.showOpenDialog(MainFrame.this);
                if (result == JFileChooser.APPROVE_OPTION) {
                    File selectedFile = fileChooser.getSelectedFile();
                    String decompiledCode = Decompiler.decompileClassFile(selectedFile);
                    outputArea.setText(decompiledCode);
                }
            }
        });

        openJarButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JFileChooser fileChooser = new JFileChooser();
                fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
                int result = fileChooser.showOpenDialog(MainFrame.this);
                if (result == JFileChooser.APPROVE_OPTION) {
                    File selectedFile = fileChooser.getSelectedFile();
                    String decompiledCode = Decompiler.decompileJarFile(selectedFile);
                    outputArea.setText(decompiledCode);
                }
            }
        });

        saveButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JFileChooser fileChooser = new JFileChooser();
                fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
                int result = fileChooser.showSaveDialog(MainFrame.this);
                if (result == JFileChooser.APPROVE_OPTION) {
                    File saveFile = fileChooser.getSelectedFile();
                    Decompiler.saveDecompiledFile(saveFile, outputArea.getText());
                }
            }
        });
    }

    /**
     * 创建按钮面板
     * @return JPanel 包含所有操作按钮
     */
    private JPanel createButtonPanel() {
        JPanel panel = new JPanel();
        panel.add(openClassButton);
        panel.add(openJarButton);
        panel.add(saveButton);
        return panel;
    }

    /**
     * 主方法,启动应用程序
     */
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new MainFrame().setVisible(true);
            }
        });
    }
}

反编译工具类

package com.dzy.decompiler;

import org.benf.cfr.reader.Main;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * 反编译工具类
 */
public class Decompiler {

    /**
     * 反编译 class 文件
     * @param classFile 要反编译的 class 文件
     * @return 反编译后的源代码
     */
    public static String decompileClassFile(File classFile) {
        if (classFile == null || !classFile.exists()) {
            return "Invalid class file.";
        }

        List<String> options = new ArrayList<>();
        options.add(classFile.getAbsolutePath());
        options.add("--outputdir");
        options.add("temp"); // 临时目录存储反编译结果

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        PrintStream printStream = new PrintStream(outputStream);
        PrintStream originalOut = System.out;
        System.setOut(printStream);

        try {
            Main.main(options.toArray(new String[0]));
        } finally {
            System.setOut(originalOut);
        }

        return outputStream.toString();
    }

    /**
     * 反编译 jar 文件
     * @param jarFile 要反编译的 jar 文件
     * @return 反编译后的源代码
     */
    public static String decompileJarFile(File jarFile) {
        if (jarFile == null || !jarFile.exists()) {
            return "Invalid JAR file.";
        }

        StringBuilder result = new StringBuilder();
        try (ZipFile zipFile = new ZipFile(jarFile)) {
            zipFile.stream()
                .filter(entry -> entry.getName().endsWith(".class"))
                .forEach(entry -> {
                    try {
                        InputStream is = zipFile.getInputStream(entry);
                        File tempClassFile = File.createTempFile("temp", ".class");
                        Files.copy(is, tempClassFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
                        String decompiledCode = decompileClassFile(tempClassFile);
                        result.append(decompiledCode).append("\n\n");
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
        } catch (IOException e) {
            e.printStackTrace();
        }

        return result.toString();
    }

    /**
     * 将反编译后的源代码保存到文件
     * @param file 要保存的文件
     * @param content 源代码内容
     */
    public static void saveDecompiledFile(File file, String content) {
        try {
            Files.write(file.toPath(), content.getBytes(), StandardOpenOption.CREATE);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

JSON 格式化工具类

package com.dzy.decompiler;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;

/**
 * JSON 格式化工具类
 */
public class JsonFormatter {
    /**
     * 格式化JSON字符串
     * @param json 输入的JSON字符串
     * @return 格式化后的JSON字符串
     */
    public static String formatJson(String json) {
        try {
            Gson gson = new GsonBuilder().setPrettyPrinting().create();
            Object jsonObj = gson.fromJson(json, Object.class);
            return gson.toJson(jsonObj);
        } catch (JsonSyntaxException e) {
            return "Invalid JSON: " + e.getMessage();
        }
    }
}

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值