`
周凡杨
  • 浏览: 235190 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java 字节码之解析一

阅读更多

 

 

一: Java 字节代码的组织形式

 

类文件 {

    OxCAFEBABE ,小版本号,大版本号,常量池大小,常量池数组,访问控制标记,当前类信息,父类信息,实现的接口个数,实现的接口信息数组,域个数,域信息数组,方法个数,方法信息数组,属性个数,属性信息数组

}

 

二: 查看方法 --- javap 命令

 

例子:有一个 Java Demo.java


public class Demo {
	private String str1;
	private String str2;
	private int num1;
	private int num2;
	public static final String STATIC_DATA = "hello world";
	
	private void sayHello1(){
		System.out.println("this is method1...");
	}
	private void sayHello2(){
		System.out.println("this is method2...");
	}
	public void sayHello3(){
		System.out.println("this is method3...");
	}
}
 

 

通过 jdk 自带的反编译工具命令 javap 可以查看 class 文件的字节码信息


D:\>javap -verbose Demo >> Demo.txt


   Demo.txt

 

Compiled from "Demo.java"
public class Demo extends java.lang.Object
  SourceFile: "Demo.java"
  minor version: 0
  major version: 49  
 
  Constant pool:
const #1 = class      #2;   //  Demo
const #2 = Asciz     Demo;
const #3 = class      #4;   //  java/lang/Object
const #4 = Asciz     java/lang/Object;
const #5 = Asciz     str1;
const #6 = Asciz     Ljava/lang/String;;
const #7 = Asciz     str2;
const #8 = Asciz     num1;
const #9 = Asciz     I;
const #10 = Asciz   num2;
const #11 = Asciz   STATIC_DATA;
const #12 = Asciz   ConstantValue;
const #13 = String  #14; //  hello world
const #14 = Asciz   hello world;
const #15 = Asciz   <init>;
const #16 = Asciz   ()V;
const #17 = Asciz   Code;
const #18 = Method       #3.#19;   //  java/lang/Object."<init>":()V
const #19 = NameAndType    #15:#16;//  "<init>":()V
const #20 = Asciz   LineNumberTable;
const #21 = Asciz   LocalVariableTable;
const #22 = Asciz   this;
const #23 = Asciz   LDemo;;
const #24 = Asciz   sayHello1;
const #25 = Field   #26.#28;  //  java/lang/System.out:Ljava/io/PrintStream;
const #26 = class    #27; //  java/lang/System
const #27 = Asciz   java/lang/System;
const #28 = NameAndType    #29:#30;//  out:Ljava/io/PrintStream;
const #29 = Asciz   out;
const #30 = Asciz   Ljava/io/PrintStream;;
const #31 = String  #32; //  this is method1...
const #32 = Asciz   this is method1...;
const #33 = Method       #34.#36;  //  java/io/PrintStream.println:(Ljava/lang/String;)V
const #34 = class    #35; //  java/io/PrintStream
const #35 = Asciz   java/io/PrintStream;
const #36 = NameAndType    #37:#38;//  println:(Ljava/lang/String;)V
const #37 = Asciz   println;
const #38 = Asciz   (Ljava/lang/String;)V;
const #39 = Asciz   sayHello2;
const #40 = String  #41; //  this is method2...
const #41 = Asciz   this is method2...;
const #42 = Asciz   sayHello3;
const #43 = String  #44; //  this is method3...
const #44 = Asciz   this is method3...;
const #45 = Asciz   SourceFile;
const #46 = Asciz   Demo.java;
 
{
public static final java.lang.String STATIC_DATA;
  Constant value: String hello world
public Demo();
  Code:
   Stack=1, Locals=1, Args_size=1
   0:      aload_0
   1:      invokespecial  #18; //Method java/lang/Object."<init>":()V
   4:      return
  LineNumberTable:
   line 2: 0
  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      5      0    this       LDemo;
 
public void sayHello3();
  Code:
   Stack=2, Locals=1, Args_size=1
   0:      getstatic   #25; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:      ldc   #43; //String this is method3...
   5:      invokevirtual  #33; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:      return
  LineNumberTable:
   line 17: 0
   line 18: 8
  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      9      0    this       LDemo;
 
}
 

 

解析:

1. 版本号   major version: 49   //java 版本 jdk1.6 显示的是 50 jdk1.5 显示的是 49 jdk1.4 显示的是 58 高版本能执行低版本的 class 文件  

2. 常量池 Constant pool

Method :方法

Field :字段

String :字符串

Asciz :签名如<init>jvm 调用,其他是不能够去调用它的

NameAndType :变量名的类型

Class :类

 

通过字节码,我们可以看到 Demo 继承于 java.lang.Object ,如果类中没有显式声明构造函数的话,编译器会插入一个缺省无参的构造函数 ( 构造函数在 JVM 级别是显示成 <init> 的普通函数 )

 

 

三: 检测代码的效率问题

 

学习 Java 的过程中,都会了解到字符串合并时要用到 StringBuffer 来代替 String ,那下面就来通过 Java 字节码来验证两种方式的效率性。

 

例子:一个 Java TestString.java

public class TestString {
    public String testString(String str1, String str2){
       return str1 + str2;
    }
    public String testStringBuffer(StringBuffer sb, String str){
       return sb.append(str).toString();
    }
}
 


 

 

javap –c TestString 后字节码信息:

 

 

Compiled from "TestString.java"
public class TestString extends java.lang.Object{
public TestString();
  Code:
   0:      aload_0
   1:      invokespecial  #8; //Method java/lang/Object."<init>":()V
   4:      return
 
public java.lang.String testString(java.lang.String, java.lang.String);
  Code:
   0:      new #16; //class java/lang/StringBuilder
   3:      dup
   4:      aload_1
   5:      invokestatic    #18; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
   8:      invokespecial  #24; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
   11:     aload_2
   12:    invokevirtual  #27; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   15:    invokevirtual  #31; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   18:    areturn
 
public java.lang.String testStringBuffer(java.lang.StringBuffer, java.lang.String);
  Code:
   0:      aload_1
   1:      aload_2
   2:      invokevirtual  #40; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
   5:      invokevirtual  #45; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
   8:      areturn
 
}
 
 

从上面编译后的字节码信息可以看出来,方法testString 调用了五个方法:new invokestatic invokespecial 和两个invokevirtual ; testStringBuffer 方法只调用了两个invokevirtual 方法。第一个方法比第二个方法多做了好多工作,其效率当然是要低的。而且我们从java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

可以看出来其实对于String 字符串合并,内部还是转化为StringBuilder 的方法调用,这是因为String 是长度不可变的,所以不如直接采用StringBuilder (与StringBuffer 长度都是可变的,只不过前者是非线程安全,后者是线程安全)进行字符串合并。
 

 

 

0
1
分享到:
评论
1 楼 wanglantao 2015-03-27  
StringBuilder.append

相关推荐

    java字节码分析工具

    Java字节码分析工具,系统分析了java字节码文件,即java class类文件,对该文件中的各种成分以树的形式描述出来,只能针对未加密的class文件,一般由标准java编译器编译生成的class文件都未加密,该系统在vs2003下面...

    从一个class文件深入理解Java字节码结构

    【Java字节码结构解析】 Java程序在执行时,首先需要通过Java编译器将源代码(.java文件)编译成二进制的字节码文件(.class文件),这些字节码由Java虚拟机(JVM)解析并执行。深入理解字节码结构有助于我们了解...

    使用Java语言实现一个漂亮的字节码解析器CLI

    一个使用Java完成的解析... 该框架的愿景为:从零到一实现一个字节码解析类库,从中了解JVM的一些规范,和Java代码编译后的组织方式。借助GraalVM的native-image工具,实现一个输出友好且漂亮的字节码解析工具(CLI)。

    class运行器v6(可以运行java字节码文件的工具 含代码)

    这些源代码可能包括VB代码以及与Java字节码解析和执行相关的逻辑。用户可以通过查看和分析这些源代码,了解如何读取和解释Java字节码,以及如何在非Java环境中执行它。 总的来说,这个工具为Java开发者提供了一种轻...

    java字节码编辑器

    Java字节码编辑器是一种工具,它允许开发者直接编辑Java程序编译后的`.class`文件,而不是反编译后再重新编译。这种编辑器对于理解、调试和优化Java代码非常有用,尤其是对于那些无法访问源代码或者需要进行底层操作...

    java字节码文件查看工具,查看class文件

    总的来说,JD-GUI是一款强大的Java字节码查看工具,它的便捷性和功能强大性使得开发者可以更深入地理解并分析Java程序。无论是为了学习、调试还是逆向工程,掌握如何有效地使用此类工具都是Java开发者必备的技能之一...

    Java字节码(.class文件)格式详解((转载)

    Java字节码是Java程序在运行时被JVM(Java虚拟机)解释执行的一种中间语言。每个Java类都由一个`.class`文件表示,其中包含了编译后的字节码指令。`.class`文件的结构非常严谨,它不仅包含了类的信息,如类名、方法...

    JAVA字节码操作库 BCEL

    BCEL(Byte Code Engineering Library)是Java开发的一个重要工具,主要用于处理Java字节码。它为开发者提供了一种深入理解与操作Java类文件的底层机制,允许分析、创建、修改和优化字节码。在软件工程中,BCEL在...

    java字节码文件反编译

    Java字节码文件反编译是一项重要的技术,它允许开发者查看和理解已编译的Java类文件(.class文件)内部的源代码结构。在Java中,源代码被编译成字节码,这是一种中间语言,由Java虚拟机(JVM)执行。然而,有时我们...

    Java字节码反编译

    Java字节码反编译是Java开发者在进行代码分析、逆向工程或学习类库源码时常用的一种技术。它允许我们将已经编译过的.class文件转换回可读性更强的.java源代码文件,以便理解程序的运行逻辑。在这个过程中,我们通常...

    cpp-C语言实现的一个解析JAVAclass字节码的库

    Java字节码是一种中间代码,它是源代码(.java文件)经过编译器处理后的结果(.class文件)。这种字节码设计的目的是为了实现平台无关性,因为JVM可以在任何支持它的操作系统上解释并执行这些字节码。 C++库解析...

    字节码解析01.rar

    总之,"字节码解析01.rar"这个教程提供了学习Java字节码解析的基础,尽管它可能未涵盖所有细节,但对于初学者来说,是一个不错的起点。通过实践和进一步学习,开发者将能够全面掌握Java字节码的奥秘,提升自身在Java...

    XJad 字节码反编译工具

    在IT行业中,字节码反编译是一种技术,它允许我们查看和理解那些由编译器生成的中间语言代码,通常是Java字节码或.NET CLR字节码。这些字节码是不可读的机器语言,但通过反编译,我们可以将其转化为更易于人类理解的...

    Java字节码和asm入门资料

    Java字节码是Java虚拟机(JVM)执行程序的核心组成部分,它是一种低级的、平台无关的指令集。ASM是一个开源的Java字节码操控和分析框架,它可以直接用来生成和修改Java类文件,是Java动态代理和字节码增强技术的重要...

    java字节码查看工具

    java字节码查看工具

    java字节码反编译工具

    Java字节码反编译工具是开发者们在研究或调试Java程序时常用的一种辅助软件,它能够将已编译的Java字节码(.class文件)转换回可读性较高的源代码形式。这样的工具使得开发者可以查看和理解第三方库或者无法获取源代码...

    Java字节码加密工具

    Java字节码加密工具是一种用于保护Java应用程序源代码安全的工具。在软件开发过程中,源代码是开发者的心血结晶,包含了许多重要的商业逻辑和技术细节。然而,Java的字节码(.class文件)虽然相对于源代码(.java...

    java字节码例子 可以动态修改类 bcel

    BCEL(Byte Code Engineering Library),全称Java字节码操纵库,是Apache软件基金会下的Jakarta项目之一。BCEL提供了一套API,允许开发者对Java类进行分析、创建和修改。通过BCEL,我们可以深入到字节码层面,实现...

Global site tag (gtag.js) - Google Analytics