字节码文件 Krains 2020-08-04
编写的Java代码
public class MethodInnerStructTest extends Object implements Comparable<String>, Serializable {
// filed
public int num = 10;
private static String str = "test";
// 默认构造器
// 方法
public void test1(){
int count = 20;
System.out.println("count=" + count);
}
public static int test2(int cal){
int result = 0;
try{
int value = 30;
result = value / cal;
}catch(Exception e){
e.printStackTrace();
}
return result;
}
@Override
public int compareTo(String o) {
return 0;
}
}
反编译
javap -v -p MethodInnerStructTest.class
得到反编译的字节码文件,这些信息都会通过classloader加载到方法区当中,但在运行时方法区中还包含了加载该class文件的classloader信息,当前只是反编译,没有经过classloader。
《深入理解Java虚拟机》书中对方法区(Method Area)存储内容描述如下:它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。
类型信息
对每个加载的类型(类class、接口interface、枚举enum、注解annotation),JVM必须在方法区中存储以下类型信息:
- 这个类型的完整有效名称(全名=包名.类名)
- 这个类型直接父类的完整有效名(对于interface或是java.lang.object,都没有父类)
- 这个类型的修饰符(public,abstract,final的某个子集)
- 这个类型直接接口的一个有序列表
域信息
JVM必须在方法区中保存类型的所有域的相关信息以及域的声明顺序。
域的相关信息包括:域名称、域类型、域修饰符(public,private,protected,static,final,volatile,transient的某个子集)
方法(Method)信息
JVM必须保存所有方法的以下信息,同域信息一样包括声明顺序:
- 方法名称
- 方法的返回类型(或void)
- 方法参数的数量和类型(按顺序)
- 方法的修饰符(public,private,protected,static,final,synchronized,native,abstract的一个子集)
- 方法的字节码(bytecodes)、操作数栈、局部变量表及大小(abstract和native方法除外)
- 异常表(abstract和native方法除外)
每个异常处理的开始位置、结束位置、代码处理在程序计数器中的偏移地址、被捕获的异常类的常量池索引
non-final的类变量
静态变量和类关联在一起,随着类的加载而加载,他们成为类数据在逻辑上的一部分
类变量被类的所有实例共享,即使没有类实例时,你也可以访问它
全局常量
全局常量就是使用 static final 进行修饰
被声明为final的类变量的处理方法则不同,每个全局常量在编译的时候就会被分配了。
常量池
常量池表(Constant Pool Table)是Class文件的一部分,用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
运行时常量池 VS 常量池
字节码文件中含有常量池,里面有一些符号引用,clas文件加载到方法区之后,常量池就变成了运行时常量池。
常量池表(Constant Pool Table),包括各种字面量和对类型、域和方法的符号引用
test1方法编译后的代码指令,里边用到的#
都是符号引用。
为什么需要常量池
一个java源文件中的类、接口,编译后产生一个字节码文件。而Java中的字节码需要数据支持,通常这种数据会很大以至于不能直接存到字节码里,可以换另一种方式,可以存到常量池,这个字节码包含了指向常量池的引用。
而在运行时常量池中,就统一了所有字节码的常量池,这样也能够复用一些字面量、域、方法等信息,节省内存空间。
0: bipush 20
2: istore_1
3: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
6: new #4 // class java/lang/StringBuilder
9: dup
10: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
13: ldc #6 // String count=
15: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
18: iload_1
19: invokevirtual #8 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
22: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
25: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
28: return
完整的class文件
Classfile /home/zsh/workplace/idea/leetcode/out/production/String/MethodInnerStructTest.class
Last modified 2020-8-4; size 1570 bytes
MD5 checksum 7bd5c5126ee7ab811c5336bcf5e8d30c
Compiled from "MethodInnerStructTest.java"
// 类型信息
public class MethodInnerStructTest extends java.lang.Object implements java.lang.Comparable<java.lang.String>, java.io.Serializable
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
// 常量池
Constant pool:
#1 = Methodref #18.#52 // java/lang/Object."<init>":()V
#2 = Fieldref #17.#53 // MethodInnerStructTest.num:I
#3 = Fieldref #54.#55 // java/lang/System.out:Ljava/io/PrintStream;
#4 = Class #56 // java/lang/StringBuilder
#5 = Methodref #4.#52 // java/lang/StringBuilder."<init>":()V
#6 = String #57 // count=
#7 = Methodref #4.#58 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#8 = Methodref #4.#59 // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
#9 = Methodref #4.#60 // java/lang/StringBuilder.toString:()Ljava/lang/String;
#10 = Methodref #61.#62 // java/io/PrintStream.println:(Ljava/lang/String;)V
#11 = Class #63 // java/lang/Exception
#12 = Methodref #11.#64 // java/lang/Exception.printStackTrace:()V
#13 = Class #65 // java/lang/String
#14 = Methodref #17.#66 // MethodInnerStructTest.compareTo:(Ljava/lang/String;)I
#15 = String #67 // test
#16 = Fieldref #17.#68 // MethodInnerStructTest.str:Ljava/lang/String;
#17 = Class #69 // MethodInnerStructTest
#18 = Class #70 // java/lang/Object
#19 = Class #71 // java/lang/Comparable
#20 = Class #72 // java/io/Serializable
#21 = Utf8 num
#22 = Utf8 I
#23 = Utf8 str
#24 = Utf8 Ljava/lang/String;
#25 = Utf8 <init>
#26 = Utf8 ()V
#27 = Utf8 Code
#28 = Utf8 LineNumberTable
#29 = Utf8 LocalVariableTable
#30 = Utf8 this
#31 = Utf8 LMethodInnerStructTest;
#32 = Utf8 test1
#33 = Utf8 count
#34 = Utf8 test2
#35 = Utf8 (I)I
#36 = Utf8 value
#37 = Utf8 e
#38 = Utf8 Ljava/lang/Exception;
#39 = Utf8 cal
#40 = Utf8 result
#41 = Utf8 StackMapTable
#42 = Class #63 // java/lang/Exception
#43 = Utf8 compareTo
#44 = Utf8 (Ljava/lang/String;)I
#45 = Utf8 o
#46 = Utf8 (Ljava/lang/Object;)I
#47 = Utf8 <clinit>
#48 = Utf8 Signature
#49 = Utf8 Ljava/lang/Object;Ljava/lang/Comparable<Ljava/lang/String;>;Ljava/io/Serializable;
#50 = Utf8 SourceFile
#51 = Utf8 MethodInnerStructTest.java
#52 = NameAndType #25:#26 // "<init>":()V
#53 = NameAndType #21:#22 // num:I
#54 = Class #73 // java/lang/System
#55 = NameAndType #74:#75 // out:Ljava/io/PrintStream;
#56 = Utf8 java/lang/StringBuilder
#57 = Utf8 count=
#58 = NameAndType #76:#77 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#59 = NameAndType #76:#78 // append:(I)Ljava/lang/StringBuilder;
#60 = NameAndType #79:#80 // toString:()Ljava/lang/String;
#61 = Class #81 // java/io/PrintStream
#62 = NameAndType #82:#83 // println:(Ljava/lang/String;)V
#63 = Utf8 java/lang/Exception
#64 = NameAndType #84:#26 // printStackTrace:()V
#65 = Utf8 java/lang/String
#66 = NameAndType #43:#44 // compareTo:(Ljava/lang/String;)I
#67 = Utf8 test
#68 = NameAndType #23:#24 // str:Ljava/lang/String;
#69 = Utf8 MethodInnerStructTest
#70 = Utf8 java/lang/Object
#71 = Utf8 java/lang/Comparable
#72 = Utf8 java/io/Serializable
#73 = Utf8 java/lang/System
#74 = Utf8 out
#75 = Utf8 Ljava/io/PrintStream;
#76 = Utf8 append
#77 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder;
#78 = Utf8 (I)Ljava/lang/StringBuilder;
#79 = Utf8 toString
#80 = Utf8 ()Ljava/lang/String;
#81 = Utf8 java/io/PrintStream
#82 = Utf8 println
#83 = Utf8 (Ljava/lang/String;)V
#84 = Utf8 printStackTrace
{
// 域信息/属性
public int num;
descriptor: I
flags: ACC_PUBLIC // 访问修饰符
// 如果是final修饰的static常量,则会在编译之后就初始化了,而不是在初始化阶段
private static java.lang.String str;
descriptor: Ljava/lang/String;
flags: ACC_PRIVATE, ACC_STATIC
// 默认构造器
public MethodInnerStructTest();
descriptor: ()V // 返回值 void
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 10
7: putfield #2 // Field num:I
10: return
LineNumberTable:
line 3: 0
line 5: 4
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 this LMethodInnerStructTest;
// 方法
public void test1();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=3, locals=2, args_size=1
0: bipush 20
2: istore_1
3: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
6: new #4 // class java/lang/StringBuilder
9: dup
10: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
13: ldc #6 // String count=
15: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
18: iload_1
19: invokevirtual #8 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
22: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
25: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
28: return
LineNumberTable:
line 10: 0
line 11: 3
line 12: 28
// 局部变量表
LocalVariableTable:
Start Length Slot Name Signature
0 29 0 this LMethodInnerStructTest;
3 26 1 count I
public static int test2(int);
descriptor: (I)I
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=3, args_size=1
0: iconst_0
1: istore_1
2: bipush 30
4: istore_2
5: iload_2
6: iload_0
7: idiv
8: istore_1
9: goto 17
12: astore_2
13: aload_2
14: invokevirtual #12 // Method java/lang/Exception.printStackTrace:()V
17: iload_1
18: ireturn
// 异常表
Exception table:
from to target type
2 9 12 Class java/lang/Exception
LineNumberTable:
line 15: 0
line 17: 2
line 18: 5
line 21: 9
line 19: 12
line 20: 13
line 22: 17
LocalVariableTable:
Start Length Slot Name Signature
5 4 2 value I
13 4 2 e Ljava/lang/Exception;
0 19 0 cal I
2 17 1 result I
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 12
locals = [ int, int ]
stack = [ class java/lang/Exception ]
frame_type = 4 /* same */
public int compareTo(java.lang.String);
descriptor: (Ljava/lang/String;)I
flags: ACC_PUBLIC
Code:
stack=1, locals=2, args_size=2
0: iconst_0
1: ireturn
LineNumberTable:
line 27: 0
LocalVariableTable:
Start Length Slot Name Signature
0 2 0 this LMethodInnerStructTest;
0 2 1 o Ljava/lang/String;
public int compareTo(java.lang.Object);
descriptor: (Ljava/lang/Object;)I
flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: aload_1
2: checkcast #13 // class java/lang/String
5: invokevirtual #14 // Method compareTo:(Ljava/lang/String;)I
8: ireturn
LineNumberTable:
line 3: 0
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this LMethodInnerStructTest;
// 类加载过程中的初始化阶段的<clinit>
static {};
descriptor: ()V
flags: ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: ldc #15 // String test
2: putstatic #16 // Field str:Ljava/lang/String;
5: return
LineNumberTable:
line 6: 0
}
Signature: #49 // Ljava/lang/Object;Ljava/lang/Comparable<Ljava/lang/String;>;Ljava/io/Serializable;
SourceFile: "MethodInnerStructTest.java"
- Python进行数据可视化分析快速教程实例
- 一个抓取豆瓣图书的开源爬虫的详细步骤
- Java 8 Stream 教程 (三)
- silverlight ListBox 多列图片效果
- ZooKeeper构建分布式锁(选译)
- Caliburn.Micro学习笔记(二)----Actions
- 每天一个Linux命令:find
- textFile构建RDD的分区及compute计算策略
- 一个基于Flask和MongoDB的CMS内容管理系统
- c++多重继承小结
- 初识PB级数据分析利器Prestodb
- 使用python实现RESTful API服务器端的思路
- c++ this *this
- JAVA之ClassLoader
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 漫画:什么是 “抽象工厂模式” ?
- 啥?Grafana 还能为日志添加告警?
- Docker映射详解,没问题了!
- 写了很久!详细理解Spring和IoC
- 一位摸金校尉决定转行前端
- CentOS7下搭建并体验HFish开源蜜罐系统
- 唐朝人更懂React
- 唐朝人更懂React
- 一起学习PHP的runkit扩展如何使用
- CentOS7下部署开源网络流量回溯分析系统Moloch
- spring源码(八)
- 通过源码理解rarp协议(基于linux1.2.13)
- 详解Im2Col+Pack+Sgemm策略更好的优化卷积运算
- Kubernetes 使用 ceph-csi 消费 RBD 作为持久化存储
- 聊聊调试的那些事,超实用!!!