java字节码文件详解

看过java虚拟机。。。

Java为什么能够支持跨平台,其实关键就是在于其*.class字节码文件,因为*.class字节码文件有一个统一标准的规范,里面是JVM运行的时需要的相关指令,各家的JVM必须能够解释编译执行标准字节码文件,因此Java是一种跨平台语言,再想想C++/C等语言为什么不是跨平台的,就是因为其源文件经过编译后生成的就是针对特定机器的汇编代码

字节码文件解析

在解析之前最好下载一个工具方便查看(Bytecode viewer),当然也可以不用下载,直接使用JDK自带的命令如javap –c –s –l –verbose (字节码文件去掉扩展名)

一个简单的程序

  1. public class Test {  
  2. private static final int MAX_COUNT=1000;  
  3. private static int count=0;  
  4. public int bar() throws Exception{  
  5.     if(++count>=MAX_COUNT){  
  6.         count=0;  
  7.         throw new Exception("count overflow");  
  8.     }  
  9.     return count;  
  10. }  
  11. }  
public class Test {
private static final int MAX_COUNT=1000;
private static int count=0;
public int bar() throws Exception{
	if(++count>=MAX_COUNT){
		count=0;
		throw new Exception("count overflow");
	}
	return count;
}
}

运行工具软件查看得下图:

看到了吧,一个字节码文件由6部份组成,先看第一部份General Information,这一部份中说明了JDK使用的版本号Major version=51表示使用的是JDK 7,Minor version=0表示的是次版本号,这也限制了运行此字节码文件需要的最低JDK版本号,不信你可以试试下面这条语句,其实就是从字节码文件中获取到class的版本号

  1. System.out.println(System.getProperty("java.class.version"));  
System.out.println(System.getProperty("java.class.version"));

下面是constant pool=35,常量池中存放着类中定义的所有常量,大致包括类名,方法名,特征符以及字符串等,Access flag=0x0021[public]表识该类的访问权限,This class=cp_info_#1<Test>其中cp是const pool的缩写,表示这个类的信息保存在了1号常量池中,下面讲到constant pool时再说,super class=cp_info_#3也表示同一个意思,Interface count=0表示类没有实现接口,Fields count=2说明类中定义了两个成员变量,不信你看看刚才的源文件是不是有两个变量,Methods count=3表明类中定义的方法数是3(clinit对静态变量进行赋值由JVM调用, init为类的构造函数 bar用户自定义函数),Attribute count=1表示是类格式属性看看常量池如下,不截图了

  1. <SPAN style="FONT-SIZE: 18px">[01] CONSTANT_Class_info  
  2.     Classname:cp_info_#2<Test>  
  3. 表示Classname存放在2号常量池中  
  4. [02] CONSTANT_Utf8_info  
  5.     Length of byte array :4  
  6.     Length of string:4  
  7.     String: Test  
  8. </SPAN>  
[01] CONSTANT_Class_info
	Classname:cp_info_#2<Test>
表示Classname存放在2号常量池中
[02] CONSTANT_Utf8_info
	Length of byte array :4
	Length of string:4
	String: Test

表示类名是Test,长度是4,占用4个字节

其他类似,看看方法Method里的<init>即构造函数

  1. Name: cp_info_#17<<init>>  
  2. Desciptor:cp_info_#11<()V>  
  3. Access flags:0x0001[public]  
Name: cp_info_#17<<init>>
Desciptor:cp_info_#11<()V>
Access flags:0x0001[public]

Name的信息在常量池cp_info_#17中

  1. Length of byte array:6  
  2. Length of string:6  
  3. String:<init>  
Length of byte array:6
Length of string:6
String:<init>

从中可以看出其定义了字节码中类的构造函数的方法名,Descriptor描述的是函数的返回类型

  1. Length of byte array:3  
  2. Length of string:3  
  3. String:()V  
Length of byte array:3
Length of string:3
String:()V

描述了函数的返回类型即为void类型,这个Access flags就不用多说了吧,表示的是函数访问权限,缺省构造器中的“指令是面向过程的汇编语言。aload_0说的是把对象的引用保存到JVM的0号局部变量,并且把它压入栈。invokespecial #1这条命令是调用java.lang.Object中的构造(这些信息保存在1号常量项里,好处是减少字节码的长度),return是执行完毕退出的意思。Bar函数的分析类似,其字节码文件对应的指令如下

  1. getstatic #13<Test.count>  
  2. iconst_1  
  3. iadd  
  4. dup  
  5. putstatic #13<Test.count>  
  6. sipush 1000  
  7. if_icmplt 29(+17)  
  8. iconst_0  
  9. putstatic #13<Test.count>  
  10. new #25  
  11. dup  
  12. ldc #27<count overflow>  
  13. invokespecial #29<java/lang/Exception.<init>>  
  14. athrow  
  15. getstatic #13<Test.count>  
  16. ireturn  
  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值