读《深入理解Java虚拟机》有感——第一部分:Class文件的结构
1.产生
源码(.java文件)——>编译器(如:javac)——>字节码(.class文件)——>虚拟机(如:HotSpot)执行
2.Class文件
1)构成:
魔数、版本号、常量池、访问标志、索引、字段表集合、方法表集合、Signature属性表、SourseFile属性表
2)例子:
[1] .java文件
桌面/test/test/Father.java、桌面/test/test/Father_interface.java、桌面/test/Son.java ;
[2]编译出.class文件
cd 桌面/test;
桌面/test>javac Son.java;
[3]查看.class文件
桌面/test>javap -verbose Son;
Classfile /C:/Users/Administrator/Desktop/test/Son.class
Last modified 2016-4-11; size 1005 bytes
MD5 checksum 7d138d76267a6bb372eba05296e2c932魔数
Compiled from "Son.java"
接口索引,指向常量池)
SourceFile: "Son.java" 源码属性表<源码名称,指向常量池>
minor version: 0
major version: 51主板本号
flags: ACC_PUBLIC, ACC_SUPER访问标志<当前类>
Constant pool:常量池 一、符号引用{
#1 = Methodref #16.#33 // test/Father."<init>":()V
#2 = Fieldref #15.#34 // test/Son.sId_literal:I 《字段》符号引用
#3 = Fieldref #35.#36 // java/lang/System.out:Ljava/io/PrintStream;
#4 = Class #37 // java/lang/StringBuilder 《类/接口》符号引用
#5 = Methodref #4.#33 // java/lang/StringBuilder."<init>":()V 《类方法》符号引用
#6 = String #38 // statical_sId = 《字面量——静态字段》符号引用
#7 = Methodref #4.#39 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/Strin
gBuilder;
#8 = Fieldref #15.#40 // test/Son.statical_sId:I
#9 = Methodref #4.#41 // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
#10 = Methodref #4.#42 // java/lang/StringBuilder.toString:()Ljava/lang/String;
#11 = Methodref #43.#44 // java/io/PrintStream.println:(Ljava/lang/String;)V
#12 = String #45 // Son实例构造器! 《字面量——System.out的字符串》符号引用
#13 = String #46 // hello!this is son!
#14 = String #47 // Son类构造器<clinit>执行!
#15 = Class #48
#16 = Class #49
#17 = Class #50 // test/Father_interface 3 }
二、常量类型{
#18 = Utf8 final_sId UTF-8编码的字符串
#19 = Utf8 I
#20 = Utf8 ConstantValue
#21 = Integer 整型字面量
#22 = Utf8 statical_sId
#23 = Utf8 sId_literal
#24 = Utf8 sId_nonLiteral
#25 = Utf8 <init>
#26 = Utf8 ()V /**返回类型*/
#27 = Utf8 Code
#28 = Utf8 LineNumberTable
#29 = Utf8 sayHello
#30 = Utf8 <clinit>
#31 = Utf8 SourceFile
#32 = Utf8 Son.java
} 三、符号引用、数据{
#33 = NameAndType #25:#26 // "<init>":()V 《字段/方法部分》符号引用
#34 = NameAndType #23:#19 // sId_literal:I
#35 = Class #51 // java/lang/System
#36 = NameAndType #52:#53 // out:Ljava/io/PrintStream;
#37 = Utf8 java/lang/StringBuilder
#38 = Utf8 statical_sId =
#39 = NameAndType #54:#55 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#40 = NameAndType #22:#19 // statical_sId:I
#41 = NameAndType #54:#56 // append:(I)Ljava/lang/StringBuilder;
#42 = NameAndType #57:#58 // toString:()Ljava/lang/String;
#43 = Class #59 // java/io/PrintStream
#44 = NameAndType #60:#61 // println:(Ljava/lang/String;)V
#45 = Utf8 Son实例构造器! }符号引用
#46 = Utf8 hello!this is son!
#47 = Utf8 Son类构造器<clinit>执行!
#48 = Utf8 test/Son
#49 = Utf8 test/Father
#50 = Utf8 test/Father_interface
#51 = Utf8 java/lang/System
#52 = Utf8 out
#53 = Utf8 Ljava/io/PrintStream;
#54 = Utf8 append
#55 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder;
#56 = Utf8 (I)Ljava/lang/StringBuilder;
#57 = Utf8 toString
#58 = Utf8 ()Ljava/lang/String;
#59 = Utf8 java/io/PrintStream
#60 = Utf8 println
#61 = Utf8 (Ljava/lang/String;)V
{
public test.Son();方法表——实例构造器
flags: ACC_PUBLIC
Code:
stack=3, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method test/Father."<init>":()V
4: aload_0
5: bipush 123
7: putfield #2 // Field sId_literal:I
10: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
13: new #4 // class java/lang/StringBuilder
16: dup
17: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
20: ldc #6 // String statical_sId =
22: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/
lang/StringBuilder;
25: getstatic #8 // Field statical_sId:I
28: invokevirtual #9 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilde
r;
31: invokevirtual #10 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
34: invokevirtual #11 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
37: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
40: ldc #12 // String Son实例构造器!
42: invokevirtual #11 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
45: sipush 333
48: putstatic #8 // Field statical_sId:I
51: return
LineNumberTable:
line 15: 0
line 7: 4
line 16: 10
line 17: 37
line 18: 45
line 19: 51
public void sayHello();方法表——sayHello()
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #13 // String hello!this is son!
5: invokevirtual #11 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 21: 0
line 22: 8
static {};方法表——类构造器(静态代码块)
flags: ACC_STATIC
Code:
stack=3, locals=0, args_size=0
0: bipush 123
2: putstatic #8 // Field statical_sId:I
5: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
8: new #4 // class java/lang/StringBuilder
11: dup
12: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
15: ldc #6 // String statical_sId =
17: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/
lang/StringBuilder;
20: getstatic #8 // Field statical_sId:I
23: invokevirtual #9 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilde
r;
26: invokevirtual #10 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
29: invokevirtual #11 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
32: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
35: ldc #14 // String Son类构造器<clinit>执行!
37: invokevirtual #11 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
40: return
LineNumberTable:
line 6: 0
line 11: 5
line 12: 32
line 13: 40
}
3.分析
| 魔数 | 版本号 | 常量池 | 访问标志 | 索引 | 字段表集合 |
|
因为后缀名是可以改的,所以 用它来确定真的是.class文件 |
44=JDK1.0 45=jdk1.1 .... |
字面量: 基本类型数据值 <int、double等> 符号引用: <指向UTF-8字符串> 记录类信息 访问标志 全限定名 记录方法 简单名称 返回类型 参数列表 记录成员属性 简单名称 访问标志 返回类型 |
本类索引 继承父类索引 实现接口索引 <指向”常量池“符号引用, 记录类信息> |
每张表: 访问标志 //指向常量池-符号引用-成员 名称 描述 返回类型 //指向常量池-符号引用-成员 附加属性表 ————ConstantValue表 静态成员才有此属性表,如果被final修饰,就直接把取值(常量池-字面量)写到表中 ————Signature表 //记录泛型信息 |
|
|
方法表集合 |
Signature表 |
SourseFile属性表 |
|||
|
每张表: 访问标志 //指向常量池-符号引用-方法 名称 描述 返回类型、参数列表 //指向常量池-符号引 用-方法 附加属性表 ————Code表 虚拟机字节码指令 (方法内容,抽象方 法无此属性表) ————Linumber表 ————局部变量表 ————异常表 ————Signature表 记录泛型信息
|
记录本类泛型信息 |
表1: <本类> 对应源码文件名称索引 表2: <内部类> 对应源码文件名称索引 .... |
4.相关术语
1)特征签名
-方法表中所有“参数-描述”的集合,指向常量池的符号引用
2)元数据
-方法、字段、类和包的描述信息(即字节码中非虚拟机字节码指令部分)
3)<client>()方法
·定义:
-即“类构造器”,是由编译器自动收集类中类变量的赋值和静态语句块中语句合并产生,在编译过程中,由编译器将该方法的bit流写入.Class文件。
·例子:
-收集“类变量的赋值”
Person.java文件:static int i =20;——————>Person.Class文件: static Person{ int i =20;}
-收集“静态语句块中语句”
Person.java文件:static {Person.i =50;}——————>Person.Class文件: static Person{ int i =20; i =50;}
·性质:
-按在.java源文件中出现的顺序,依次进行收集;
-“类构造器”并不是必须被产生的,因为一个类或接口可以没有静态语句块和类变量的赋值操作;
-接口也中可以有“类构造器”,因为从语法上,虽然接口中不能含static{}静态代码块,但是可以含“类变量的赋值”;
读《深入理解Java虚拟机》有感——第一部分:Class文件的结构的更多相关文章
- 【深入理解JAVA虚拟机】第一部分.走进Java
Java技术体系 如果仅从传统意义上来看,Sun官方所定义的Java技术体系包括以下几个组成部分:Java程序设计语言各种硬件平台上的Java虚拟机Class文件格式Java API类库来自商业机构和 ...
- 深入理解Java虚拟机(第2版) 笔记目录
本篇为读深入理解Java虚拟机(第2版)一书的笔记目录. Java 运行期数据区 Java 垃圾回收算法 Java 内存分配策略 Java 类文件结构 Java 加载.链接.初始化 Java 类加载器
- 读《深入理解Java虚拟机》
Java虚拟机运行时数据区 对象的创建 Java创建对象,在语言层面上使用new关键字.虚拟机遇到new关键字时,会检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的 ...
- 深入理解Java虚拟机--下
深入理解Java虚拟机--下 参考:https://www.zybuluo.com/jewes/note/57352 第10章 早期(编译期)优化 10.1 概述 Java语言的"编译期&q ...
- 《深入理解Java虚拟机》-----第6章 类文件结构——Java高级开发必须懂的
代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,却是编程语言发展的一大步. 6.1 概述 记得在第一节计算机程序课上我的老师就讲过:“计算机只认识0和1,所以我们写的程序需要经编译器翻 ...
- 深入理解Java虚拟机(类文件结构+类加载机制+字节码执行引擎)
目录 1.类文件结构 1.1 Class类文件结构 1.2 魔数与Class文件的版本 1.3 常量池 1.4 访问标志 1.5 类索引.父索引与接口索引集合 1.6 字段表集合 1.7 方法集合 1 ...
- jvm--深入理解java虚拟机 精华总结(面试)(转)
深入理解java虚拟机 精华总结(面试)(转) 原文地址:http://www.cnblogs.com/prayers/p/5515245.html 一.运行时数据区域 3 1.1 程序计数器 3 1 ...
- 2018.4.23 深入理解java虚拟机(转)
深入理解java虚拟机 精华总结(面试) 一.运行时数据区域 Java虚拟机管理的内存包括几个运行时数据内存:方法区.虚拟机栈.本地方法栈.堆.程序计数器,其中方法区和堆是由线程共享的数据区,其他几个 ...
- 《深入理解Java虚拟机》学习笔记
<深入理解Java虚拟机>学习笔记 一.走近Java JDK(Java Development Kit):包含Java程序设计语言,Java虚拟机,JavaAPI,是用于支持 Java 程 ...
随机推荐
- JPA学习(1)基础认知
JPA 是什么 Java Persistence API:用于对象持久化的API. Java EE 5.0 平台标准的 ORM 规范,使得应用程序以统一的方式访问持久层: JPA和Hibernate的 ...
- 由简入繁实现Jquery树状结构
在项目中,我们经常会需要一些树状结构的样式来显示层级结构等,比如下图的样式,之前在学.net的时候可以直接拖个服务端控件过来直接使用非常方便.但是利用Jquery的一些插件,也是可以实现这些效果的,比 ...
- Windows程序==>>使用ListView控件展示数据
使用ListView控件展示数据 01.ImageList控件 1.了解了解 属性 说明 Images 储存在图像列表中的所有图像 ImageSize 图像列表中图像的大小 Trans ...
- Android应用开发基础之四:网络编程(一)
网络图片查看器 确定图片的网址 发送http请求 URL url = new URL(address); //获取连接对象,并没有建立连接 HttpURLConnection conn = (Http ...
- 跟踪js文件作为iframe页面不起作用时(淘宝天猫)
跟踪文件 (function(win, doc) { var s = doc.createElement("script"), h = doc.getElementsByTagNa ...
- 【Android】开源项目UI控件分类汇总之Dialog
接前文ProgressBar:Android开发的宝库越来越多,我开发中有需要的组件,主要参考Trinea的大作Android开源项目分类汇总(包含了后面的绝大多数).CSDN上直接拿来用!最火的An ...
- 系统自带的NSJSONSerialization解析json文件
#import "ViewController.h" #import "Student.h" #import "GDataXMLNode.h" ...
- Maven学习——安装与修改Maven的本地仓库路径
一.Maven的下载安装配置 1.1.下载 官网 http://maven.apache.org/download.cgi 1.2.安装配置 apache-maven-3.3.3-bin.zip 解压 ...
- Gradle安装
最近在学Android,而Android是由Gradle来构建的:Gradle是一个基于 JVM 的构建工具.所以开始学习Android之前,先进行Gradle安装与学习: mac: 使用SDKMAN ...
- Objective-C Reflection(Objective-C 反射机制)实用随笔笔记(持续更新)
前言:本篇文章就"Objective-C 反射机制"使用方面进行叙述,不会涉及太多理论论述,因为"Objective-C 反射机制"理论论述在网上搜索一大把,本 ...