深入理解java虚拟机一 JAVA运行时内存区域与class文件
一?JAVA運(yùn)行時(shí)內(nèi)存區(qū)域
JVM在加載class文件時(shí),會(huì)將class文件定義的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)為運(yùn)行時(shí)內(nèi)存中的數(shù)據(jù),那么jvm是如何安排運(yùn)行時(shí)的內(nèi)存區(qū)域呢?
jvm將運(yùn)行時(shí)內(nèi)存劃分為以下幾個(gè)部分:
堆:所有線程共享
方法區(qū):類信息、靜態(tài)變量、常量等
運(yùn)行時(shí)常量池:class文件的常量池(字面常量和符號(hào)引用)+運(yùn)行時(shí)產(chǎn)生的常量
程序計(jì)數(shù)器: ?當(dāng)前線程執(zhí)行的字節(jié)碼的行號(hào)指示器
虛擬機(jī)棧:棧幀 = 本地局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接、出口信息
本地方法棧:native方法
直接內(nèi)存:不屬于jvm管理,但是在nio中,會(huì)使用native方法申請(qǐng)堆外內(nèi)存,并在java堆中保存其引用。
其中,堆和方法區(qū)是所有的線程所共享的,而虛擬機(jī)棧、本地方法棧和程序計(jì)數(shù)器是各線程所獨(dú)享的。
二 class文件
class文件是怎樣定義的呢?它與java運(yùn)行時(shí)內(nèi)存是什么關(guān)系呢?
class文件格式:
u4 魔數(shù)
u2 class文件版本號(hào)
u2 class文件版本號(hào)
u2 constant_pool_count ? ?表示常量池容量大小,從1開始計(jì)數(shù);
常量池中主要存放兩大類:字面常量和符號(hào)引用
符號(hào)引用又包含三類:類、接口的全限定名,字段名稱和描述,方法名稱和描述
cp_info constant_pool
共定義了11種常量項(xiàng)?
?其中,有CONSTANT_Fieldref_info,會(huì)有聲明字段的類/接口和字段的名稱及描述符等;
?
?與后面的字段表/方法表略有不同,但是會(huì)復(fù)用相同的簡單名稱和描述符。
?這里的只會(huì)包含在類中被使用的field和method。
? ? ? 當(dāng)前代碼所屬的類是D,要把一個(gè)符號(hào)引用N解析成一個(gè)來自類或接口C的直接引用:
這個(gè)發(fā)生在何地?可能發(fā)生在方法的字節(jié)碼中:
Classfile /Users/wangzx/IdeaProjects/devep_java/spring_java/target/classes/com/sankuai/sc/t/test2.class
Last modified 2016-6-5; size 546 bytes
MD5 checksum c1c0289a9a434d71f7e4a04adfd366c3
Compiled from "test2.java"
public class com.sankuai.sc.t.test2
SourceFile: "test2.java"
minor version: 0
major version: 49
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #5.#22 // java/lang/Object."<init>":()V
#2 = Fieldref #23.#24 // com/sankuai/sc/t/A.a:I
#3 = Methodref #4.#25 // com/sankuai/sc/t/test2.inc:(Lcom/sankuai/sc/t/A;)I
#4 = Class #26 // com/sankuai/sc/t/test2
#5 = Class #27 // java/lang/Object
#6 = Utf8 m
#7 = Utf8 I
#8 = Utf8 <init>
#9 = Utf8 ()V
#10 = Utf8 Code
#11 = Utf8 LineNumberTable
#12 = Utf8 LocalVariableTable
#13 = Utf8 this
#14 = Utf8 Lcom/sankuai/sc/t/test2;
#15 = Utf8 inc
#16 = Utf8 (Lcom/sankuai/sc/t/A;)I
#17 = Utf8 a
#18 = Utf8 Lcom/sankuai/sc/t/A;
#19 = Utf8 inccc
#20 = Utf8 SourceFile
#21 = Utf8 test2.java
#22 = NameAndType #8:#9 // "<init>":()V
#23 = Class #28 // com/sankuai/sc/t/A
#24 = NameAndType #17:#7 // a:I
#25 = NameAndType #15:#16 // inc:(Lcom/sankuai/sc/t/A;)I
#26 = Utf8 com/sankuai/sc/t/test2
#27 = Utf8 java/lang/Object
#28 = Utf8 com/sankuai/sc/t/A
{
public int m;
flags: ACC_PUBLIC
?
public com.sankuai.sc.t.test2();
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 19: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/sankuai/sc/t/test2;
?
int inc(com.sankuai.sc.t.A);
flags:
Code:
stack=2, locals=2, args_size=2
0: aload_1
1: getfield #2 // Field com/sankuai/sc/t/A.a:I
4: iconst_1
5: iadd
6: ireturn
LineNumberTable:
line 24: 0
LocalVariableTable:
Start Length Slot Name Signature
0 7 0 this Lcom/sankuai/sc/t/test2;
0 7 1 a Lcom/sankuai/sc/t/A;
?
int inccc(com.sankuai.sc.t.A);
flags:
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: aload_1
2: invokevirtual #3 // Method inc:(Lcom/sankuai/sc/t/A;)I
5: ireturn
LineNumberTable:
line 27: 0
LocalVariableTable:
Start Length Slot Name Signature
0 6 0 this Lcom/sankuai/sc/t/test2;
0 6 1 a Lcom/sankuai/sc/t/A;
}
?
?
? ? ? 1.如果C本身就包含了簡單類型和字段描述符與N都相符的字段,則返回此字段的直接引用。 ?
? ? ? 2. 查找D是否有N,需要查找D的字段表 ? ?
3.否則,如果C實(shí)現(xiàn)了接口,則在接口中查找
4.否則,在C的父類中查找。
?
?
u2 access_flag
是否是類/接口,是否是抽象類,是否是private等,是否是final等
u2 this_class
u2 super_class
u2 interface_count
u2 interfaces
都是指 常量池中的全限定名稱,先指向類/接口索引,再找到utf-8的索引
u2 fields_count
field_info fields
字段表中會(huì)包含 字段access屬性、字段名稱索引、描述符索引以及attribute;
描述符:數(shù)組 [, V void, L 引用類型, 描述方法時(shí),先用小括號(hào)描述參數(shù)列表,后面再跟上返回值描述。
字段表中不會(huì)列出父類和超類中繼承而來的字段名
u2 methods_count
method_info methods
方法表:access屬性,名稱索引、描述索引以及attribute
如果方法沒有被override,則不會(huì)出現(xiàn)父類繼承而來的方法名
u2 attributes_count
attribute_info attributes
屬性表中最重要的要數(shù)方法表的Code屬性,其中包含了方法的具體信息,具體如下:
u2 attribute_name_index
u4 attribute_length
u2 max_stack 操作數(shù)棧的最大深度
u2 max_locals
u4 code_length
u1 code * code_length
....異常表等
?
轉(zhuǎn)載于:https://www.cnblogs.com/cycc/p/5561321.html
總結(jié)
以上是生活随笔為你收集整理的深入理解java虚拟机一 JAVA运行时内存区域与class文件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 命令行编译项目
- 下一篇: fir.im Weekly - 给 Ma