解析了一个简单的class文件

来源:互联网 发布:淘宝创意礼物店铺 编辑:程序博客网 时间:2024/05/24 08:34

用了一下午的时间,

拿着《深入java虚拟机》,

对应着chapter6的介绍,

一个字段一个字段的看了一下,

收获不小。

源文件(Act.java):

/*
* Copyright (c) 1997-1999 Bill Venners. All rights reserved.
*
* Source code file from the book "Inside the Java 2 Virtual Machine,"
* by Bill Venners, published by McGraw-Hill, 1999, ISBN: 0-07-135093-4.
*
* This source file may not be copied, modified, or redistributed
* EXCEPT as allowed by the following statements: You may freely use
* this file for your own work, including modifications and distribution
* in compiled (class files, native executable, etc.) form only. You may
* not copy and distribute this file. You may not remove this copyright
* notice. You may not distribute modified versions of this source file.
* You may not use this file in printed media without the express
* permission of Bill Venners.
*
* BILL VENNERS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
* SUITABILITY OF THIS SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR PARTICULAR PURPOSE, OR NON-INFRINGEMENT. BILL VENNERS SHALL NOT
* BE LIABLE FOR ANY DAMAGES SUFFERED BY A LICENSEE AS A RESULT OF
* USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*/

// On CD-ROM in file jvm/ex4/Act.java
class Act {

    public static void doMathForever() {
        int i = 0;
        for (;;) {
            i += 1;
            i *= 2;
        }
    }
}

字节码文件(Act.class)(略...)。

几点体会:

(1)jdk自带工具javap能够反汇编字节码(class)文件,对于javap的介绍见:

http://www.iplab.cs.tsukuba.ac.jp/~liuxj/jdk1.2/zh/docs/tooldocs/win32/javap.html

这里贴一下几个选项:

-c
输出类中各方法的未解析的代码,即构成 Java 字节码的指令。这些在 Java 虚拟机规范中说明。 输出堆栈大小、各方法的 localsargs 数。
 
-verbose

使用javap反汇编的结果如下:


E:/sun/InsideJVM/build/classes>javap -c -verbose Act
Compiled from "Act.java"
class Act extends java.lang.Object
  SourceFile: "Act.java"
  minor version: 0
  major version: 0
  Constant pool:
const #1 = Method       #3.#16; //  java/lang/Object."<init>":()V
const #2 = class        #17;    //  Act
const #3 = class        #18;    //  Object
const #4 = Asciz        <init>;
const #5 = Asciz        ()V;
const #6 = Asciz        Code;
const #7 = Asciz        LineNumberTable;
const #8 = Asciz        LocalVariableTable;
const #9 = Asciz        this;
const #10 = Asciz       LAct;;
const #11 = Asciz       doMathForever;
const #12 = Asciz       i;
const #13 = Asciz       I;
const #14 = Asciz       SourceFile;
const #15 = Asciz       Act.java;
const #16 = NameAndType #4:#5;//  "<init>":()V
const #17 = Asciz       Act;
const #18 = Asciz       java/lang/Object;

{
Act();
  Code:
   Stack=1, Locals=1, Args_size=1
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

  Code:
   Stack=1, Locals=1, Args_size=1
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return
  LineNumberTable:
   line 25: 0
  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      5      0    this       LAct;

public static void doMathForever();
  Code:
   Stack=2, Locals=1, Args_size=0
   0:   iconst_0
   1:   istore_0
   2:   iinc    0, 1
   5:   iload_0
   6:   iconst_2
   7:   imul
   8:   istore_0
   9:   goto    2

  Code:
   Stack=2, Locals=1, Args_size=0
   0:   iconst_0
   1:   istore_0
   2:   iinc    0, 1
   5:   iload_0
   6:   iconst_2
   7:   imul
   8:   istore_0
   9:   goto    2
  LineNumberTable:
   line 28: 0
   line 30: 2
   line 31: 5
  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   2      10      0    i       I

}

 

(2)对class文件的结构有了较好的理解,

编译过程中产生的符号表在这里得到了淋漓尽致的体现。

类方法所产生的指令深刻体现了JVM的栈式运行方式。

(3)几个问题:

a 反汇编出来的指令相当于汇编语言代码;

反编译器(比如 jad )能够从class文件编译出java文件,如下所示:

// Decompiled by Jad v1.5.7f. Copyright 2000 Pavel Kouznetsov.
// Jad home page: http://www.geocities.com/SiliconValley/Bridge/8617/jad.html
// Decompiler options: packimports(3) annotate
// Source File Name:   Act.java


class Act
{

    public static void doMathForever()
    {
        int i = 0;
    //    0    0:iconst_0       
    //    1    1:istore_0       
        do
            i = ++i * 2;
    //    2    2:iinc            0  1
    //    3    5:iload_0        
    //    4    6:iconst_2       
    //    5    7:imul           
    //    6    8:istore_0       
        while(true);
    //    7    9:goto            2
    }

    Act()
    {
    //    0    0:aload_0        
    //    1    1:invokespecial   #3   <Method void Object()>
    //    2    4:return         
    }
}

看来对于代码的混淆是不可避免的了(研究一下...)。

b有没有分析class文件的工具呢?开源的项目倒是不少,例如:

http://www.open-open.com/

下了一个javassist-3.1,还没有仔细看。

感觉要是有像sniffer那样分析网络包数据的图形软件就好了,不用自己用ultraedit一个字节一个字节的看了。(自己写一个?),或许已经有了...

(3)现在看完了java命令,如果再看完javac命令(2万多行,几天,几星期?),嘿嘿...

原创粉丝点击