首先要借助BinED插件查看.class文件二进制或十六进制内容内容,看图
使用方式如图 我们要找的是class文件
使用后如图
首先我们就先看一下
1的位置 ,看完资料发现我们通常叫做魔数,如图看到CA FE BA BE jvm就是通过这个魔数来判断是不是class文件的
2.第二个就是jdk的小版本号,也叫做副版本号
3.这个所指向的就是jdk的大版本号,也叫主版本号,这个可能就有疑问了,主版本号为什么是34呢,而我自己的jdk版本是1.8版本,我们可以用计算器来看一下
这时候我们就要去jdk版本的标记版本映射
!!!关于我们出现jdk版本不确定或者运行项目不匹配报错的时候,就可以对照一下
有条件的,可以自己换个jdk版本号看一下,这里郎伟就不做演示了,接下来我们就讲一下后面的一大堆的16进制数字是什么
常量池
常量池记录了jvm内的一堆常量信息,这部分由 【2个字节计数】 + 【n个cp_info结构】组成,如图标记所示
常量池中主要存放两大类常量:字面量(Literal)和符号引用(Symbolic References)。 字面量比较接近于 Java 语言层面的常量概念,如文本字符串、声明为 final 的常量值等。 而符号引用则属于编译原理方面的概念,包括了下面三类常量: 类和接口的全限定名(Fully Qualified Name)、字段的名称和描述符(Descriptor)、方法的名称和描述符
其中cp_info有多种类型:
- 直接类型,存的就是当前值,这种像Integer,Long等长度都是确定的
- 引用类型,存的是指向其他位置的指针
接下来我们就说一个案例,用过javap来反编译一下class文件
-
javap -v ClassStruct.class
- 我们也可以用idea的插件jclasslib
关于剩下的无非就是一些其他信息
- 访问标记:public abstract 等信息
- 类索引,class类型,最终指向一个utf8,标记当前类的名字
- 父类,同上
- 接口,2字节记录数量,后面记录多个接口类型
- 接下来是字段、方法、属性,都是2字节记录后面多少个,后面紧跟对应的结构体类型
如果我们可以轻松看懂javap后的格式,我们就可以轻松看懂class文件
类型 | 标识符 | 案例 | 说明 |
---|---|---|---|
数组 | [ | [Ljava.lang.String | String数组 |
对象 | L | Lcom.test.Demo | |
基本类型 | 大写字母开头 | B=byte,I=int…… |
组合类型
类型 | 案例 | 说明 |
---|---|---|
类里的属性、字段、方法等 | com.test.Demo.name:Ljava.lang.String | 英文点号隔开 |
标识什么类型 | com.test.Demo.getName:()Ljava.lang.String | 英文冒号隔开 |
方法 | (参数类型)返回值类型 | 英文括弧,后面是返回值类型 |
接下来我们就实例分析一下
关于jvm后面的内容,下篇在讲运行数据区(堆,栈,方法区)