简体   繁体   English

反编译器工具在Java中修改.class文件的源代码

[英]Decompiler tools modify the source code for .class file in java

I used DJ JAVA DECOMPILER tool to get back the source code from .class file in java. 我使用DJ JAVA DECOMPILER工具从Java中的.class文件获取源代码 What the source file it generated was having different code than what i coded earlier in the original source program . 它生成的源文件与我之前在原始源程序中编码的代码具有不同的代码

What my doubt is: 我的疑问是:

  1. Is this because of JVM does code optimization before creating the target code for better execution speed & reduce space and time complexity? 是因为JVM会在创建目标代码之前进行代码优化以提高执行速度并减少空间和时间复杂性吗?
  2. Or the decompiler tool modify the .class file code to generate the source program again? 还是反编译器工具修改.class文件代码以再次生成源程序?

See the original source program was this: 看到原始的源程序是这样的:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;


public class Test1 {
    /**
     * @param args
     * @throws SQLException
     * @throws ClassNotFoundException
     */
    public static void main(String args[]) throws SQLException, ClassNotFoundException{
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection con= DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:choxx","choxx","choxx");
        if(con==null){
            System.out.println("not established");
        }else{
            System.out.println("established");
        }

        Statement st= con.createStatement();
        //st.executeQuery("create table student if not exists(sno number(10), name varchar2(30), addr varchar(20))");
        if(st!=null){
            System.out.println("table created..");
        }

        st.execute("delete from student where addr='hyderabad'");
        ResultSet rs= st.executeQuery("select * from student");
        while(rs.next()){
            System.out.println(rs.getInt(1)+"   "+rs.getString(2)+"   "+rs.getString(3));
        }


    }
}

After decompilation what i got is: 反编译后,我得到的是:

// Decompiled by DJ v3.12.12.99 Copyright 2015 Atanas Neshkov  Date: 29-03-2015 10:55:31
// Home Page:  http://www.neshkov.com/dj.html - Check often for new version!
// Decompiler options: packimports(3) 
// Source File Name:   Test1.java

import java.io.PrintStream;
import java.sql.*;

public class Test1
{

    public Test1()
    {
    }

    public static void main(String args[])
        throws SQLException, ClassNotFoundException
    {
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:choxx", "choxx", "choxx");
        if(con == null)
            System.out.println("not established");
        else
            System.out.println("established");
        Statement st = con.createStatement();
        if(st != null)
            System.out.println("table created..");
        st.execute("delete from student where addr='hyderabad'");
        for(ResultSet rs = st.executeQuery("select * from student"); rs.next(); System.out.println(rs.getInt(1) + "   " + rs.getString(2) + "   " + rs.getString(3)));
    }
}

The Java compiler does virtually no optimization of the code produced (though there is a little, like evaluating constant expressions and inlining certain static final fields). Java编译器实际上没有对所生成的代码进行优化(尽管有一些优化,例如评估常量表达式和内联某些静态final字段)。

The thing though is that you can't realistically expect to get back the exact code you started with. 但事实是,您实际上无法期望找回最初使用的确切代码。 Java is not a scripting language, and the code is actually compiled into bytecode - the original textual source code is not stored anywhere in the classfiles. Java不是脚本语言,并且实际上将代码编译为字节码-原始文本源代码未存储在classfile中的任何位置。

The output you posted is as good as you can possibly expect. 您发布的输出是您所期望的一样好。 You're always going to lose stuff like whitespace, comments, and formatting given that that's not stored at all in the classfile. 鉴于这些内容根本没有存储在类文件中,因此您总是会丢失空白,注释和格式设置。 For the loop at the bottom, there are obviously multiple ways to write the same code, and the decompiler just chose a different way of expressing the same code. 对于底部的循环,显然有多种方法可以编写相同的代码,而反编译器只是选择了另一种表达相同代码的方法。 Since there is no way to tell which of all the possible equivalent code styles was originally used, the decompiler just guesses. 由于无法分辨最初使用的所有可能的等效代码样式中的哪种,因此反编译器只能猜测。

It's probably just the result of a heuristic that people more commonly write for loops than while loops like you originally had. 启发式的结果可能是,人们比您最初拥有的while循环更普遍地为循环编写循环。 In this particular case, noone would actually put print statements in a for loop expression like that, but heuristics can't be perfect. 在这种特殊情况下,没有人会像这样真正地将打印语句放在for循环表达式中,但是启发式方法并不是完美的。

Java Compiler does only, minimal set of optimization. Java编译器仅进行最少的优化。

Most optimization is done by JIT compiler only.(Since it has the most information about the Platform and runtime environment.) 大多数优化仅由JIT编译器完成(因为它具有有关平台和运行时环境的最多信息)。

for-loops and while-loops use an identical pattern in byte code. for循环和while循环在字节码中使用相同的模式。 This is not surprising because all while-loops can be re-written easily as an identical for-loop 这不足为奇,因为所有while循环都可以轻松地重写为相同的for循环

http://blog.jamesdbloom.com/JavaCodeToByteCode_PartOne.html http://blog.jamesdbloom.com/JavaCodeToByteCode_PartOne.html

Since in bytecode version,, the for loop and while loop looks same, the decompiler might decompile it into while loop. 由于在字节码版本中,for循环和while循环看起来相同,因此反编译器可能会将其反编译为while循环。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM