一 点睛
关于方法区的内部结构,先看看下图。
《深入理解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 方法除外)。
每个异常处理的开始位置、结束位置、代码处理在程序计数器中的偏移地址、被捕获的异常类的常量池索引。
五 class 文件说明
1 代码
/**
* 测试方法区的内部构成
*/
public class MethodInnerStrucTest extends Object implements Comparable<String>, Serializable {
// 属性
public int num = 10;
private static String str = "测试方法的内部结构";
// 构造器
// 方法
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;
}
}
2 class文件解析说明
Classfile /D:/workspace_idea5/JVMDemo/out/production/chapter09/com/atguigu/java/MethodInnerStrucTest.class
Last modified 2020-4-22; size 1626 bytes
MD5 checksum 69643a16925bb67a96f54050375c75d0
Compiled from "MethodInnerStrucTest.java"
// 类型信息
public class com.atguigu.java.MethodInnerStrucTest extends java.lang.Object
implements java.lang.Comparable<java.lang.String>, java.io.Serializable
minor version: 0
major version: 51
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #18.#52 // java/lang/Object."<init>":()V
#2 = Fieldref #17.#53 // com/atguigu/java/MethodInnerStrucTest.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 // com/atguigu/java/MethodInnerStrucTest.compareTo:(Ljava/lang/String;)I
#15 = String #67 // 测试方法的内部结构
#16 = Fieldref #17.#68 // com/atguigu/java/MethodInnerStrucTest.str:Ljava/lang/String;
#17 = Class #69 // com/atguigu/java/MethodInnerStrucTest
#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 Lcom/atguigu/java/MethodInnerStrucTest;
#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 MethodInnerStrucTest.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 测试方法的内部结构
#68 = NameAndType #23:#24 // str:Ljava/lang/String;
#69 = Utf8 com/atguigu/java/MethodInnerStrucTest
#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
private static java.lang.String str;
descriptor: Ljava/lang/String;
flags: ACC_PRIVATE, ACC_STATIC
// 方法信息
// 构造器,自动生成
public com.atguigu.java.MethodInnerStrucTest();
descriptor: ()V
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 10: 0
line 12: 4
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 this Lcom/atguigu/java/MethodInnerStrucTest;
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 17: 0
line 18: 3
line 19: 28
LocalVariableTable:
Start Length Slot Name Signature
0 29 0 this Lcom/atguigu/java/MethodInnerStrucTest;
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 21: 0
line 23: 2
line 24: 5
line 27: 9
line 25: 12
line 26: 13
line 28: 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 33: 0
LocalVariableTable:
Start Length Slot Name Signature
0 2 0 this Lcom/atguigu/java/MethodInnerStrucTest;
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 10: 0
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this Lcom/atguigu/java/MethodInnerStrucTest;
static {};
descriptor: ()V
flags: ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: ldc #15 // String 测试方法的内部结构
2: putstatic #16 // Field str:Ljava/lang/String;
5: return
LineNumberTable:
line 13: 0
}
Signature: #49 // Ljava/lang/Object;Ljava/lang/Comparable<Ljava/lang/String;>;Ljava/io/Serializable;
SourceFile: "MethodInnerStrucTest.java"