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

时间:2015-03-29 05:18:17

标签: java compiler-optimization decompiler .class-file

我使用 DJ JAVA DECOMPILER 工具从java中的 .class文件中取回源代码。它生成的源文件与原始源程序中之前编码的不同的代码相比。

我怀疑的是:

  1. 这是因为JVM在创建之前进行了代码优化 目标代码,以获得更好的执行速度&减少空间和时间 复杂?
  2. 或者反编译工具修改.class文件代码以生成 源程序再次?
  3. 查看原始源程序是这样的:

    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));
            }
    
    
        }
    }
    

    反编译后得到的是:

    // 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)));
        }
    }
    

2 个答案:

答案 0 :(得分:0)

Java编译器几乎没有对所生成的代码进行优化(尽管有一点,比如评估常量表达式并内联某些静态最终字段)。

但事实是,您无法真实地期望找回您开始使用的确切代码。 Java不是脚本语言,并且代码实际上被编译成字节码 - 原始文本源代码不存储在类文件中的任何位置。

您发布的输出与您可能期望的一样好。你总是会丢失空格,注释和格式等内容,因为它们根本没有存储在类文件中。对于底部的循环,显然有多种方法可以编写相同的代码,而反编译器只是选择了表达相同代码的不同方式。由于无法分辨最初使用的所有可能的等效代码样式,反编译器只是猜测。

这可能只是一种启发式的结果,人们更常见的是为循环而不是像你最初那样的循环。在这种特殊情况下,没有人会将print语句放在这样的for循环表达式中,但是启发式方法并不完美。

答案 1 :(得分:0)

Java编译器只进行最小化优化。

大多数优化仅由JIT编译器完成。(因为它拥有关于平台和运行时环境的最多信息。)

  

for循环和while循环在字节代码中使用相同的模式。这并不奇怪,因为所有while循环都可以轻松地重写为相同的for循环

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

由于在字节码版本中,for循环和while循环看起来相同,反编译器可能会将其反编译为while循环。