600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 【Java 虚拟机原理】栈帧 | 动态链接 | 方法区 | 字节码文件二进制分析

【Java 虚拟机原理】栈帧 | 动态链接 | 方法区 | 字节码文件二进制分析

时间:2018-06-26 17:39:36

相关推荐

【Java 虚拟机原理】栈帧 | 动态链接 | 方法区 | 字节码文件二进制分析

文章目录

前言一、方法区二、字节码二进制文件分析三、动态链接1、动态链接简介2、静态链接与动态链接3、早期绑定 和 晚期绑定4、动态链接示例

前言

" 栈帧 " 中存储的是 局部变量表 , 操作数栈 , 动态链接 , 方法出口 ;

一、方法区

字节码文件加载到内存中后 , 该文件的 Class 会存放到 方法区 ( 元空间 ) 中 ; 方法区 中存储 静态变量 , 常量 , 类元信息 ;

类元信息 是由 方法和数据组成 ;

如果定义了一个静态变量类对象 , 那么方法区中 , 的该静态变量 指向了 堆 中的对象 ;

public static HelloWorld mHelloWorld = new HelloWorld();

如果在 方法的局部变量 中创建了 类对象 , 那么 线程栈 中的局部变量 , 也会指向 堆 中的对象 ;

public static void main(String[] args) {HelloWorld helloWorld = new HelloWorld();helloWorld.add();}

类 的 实例对象 创建完成后 , 除了在类中封装的成员之外 , 还包括 " 对象头 " ( Object Header ) ,

对象头 中包含 333 部分内容 :

数据区 ;Marker Word 表及字段 ;KlassPointer 类型指针 , 指向 方法区 ( 元空间 ) 中的 类元信息 的地址 ;

二、字节码二进制文件分析

Java 源代码如下 :

public class HelloWorld {public static HelloWorld mHelloWorld = new HelloWorld();public int add() {int a = 1;int b = 1;int c = a + b;return c;}public static void main(String[] args) {HelloWorld helloWorld = new HelloWorld();helloWorld.add();}}

字节码文件二进制数据分析 :

使用二进制查看工具查看 HelloWorld.class 字节码文件 , 这些二进制数值对应的就是 JVM 指令 ;

执行

javap -v HelloWorld.class

命令 , 命令行终端输出的就是字节码二进制数据的翻译内容 ;

major version: 52配置 JDK 版本 ;

Constant pool常量池 ;

D:\java>javap -v HelloWorld.classClassfile /D:/java/HelloWorld.classLast modified -9-2; size 373 bytesMD5 checksum a9899195af11ef123968f811f4aa71f4Compiled from "HelloWorld.java"public class HelloWorldminor version: 0major version: 52flags: ACC_PUBLIC, ACC_SUPERConstant pool:#1 = Methodref#5.#16 // java/lang/Object."<init>":()V#2 = Class #17 // HelloWorld#3 = Methodref#2.#16 // HelloWorld."<init>":()V#4 = Methodref#2.#18 // HelloWorld.add:()I#5 = Class #19 // java/lang/Object#6 = Utf8<init>#7 = Utf8()V#8 = Utf8Code#9 = Utf8LineNumberTable#10 = Utf8add#11 = Utf8()I#12 = Utf8main#13 = Utf8([Ljava/lang/String;)V#14 = Utf8SourceFile#15 = Utf8HelloWorld.java#16 = NameAndType #6:#7// "<init>":()V#17 = Utf8HelloWorld#18 = NameAndType #10:#11 // add:()I#19 = Utf8java/lang/Object{public HelloWorld();descriptor: ()Vflags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: returnLineNumberTable:line 1: 0public int add();descriptor: ()Iflags: ACC_PUBLICCode:stack=2, locals=4, args_size=10: iconst_11: istore_12: iconst_13: istore_24: iload_15: iload_26: iadd7: istore_38: iload_39: ireturnLineNumberTable:line 4: 0line 5: 2line 6: 4line 7: 8public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=2, args_size=10: new #2 // class HelloWorld3: dup4: invokespecial #3 // Method "<init>":()V7: astore_18: aload_19: invokevirtual #4 // Method add:()I12: pop13: returnLineNumberTable:line 11: 0line 12: 8line 13: 13}SourceFile: "HelloWorld.java"

三、动态链接

1、动态链接简介

动态链接 又称为 运行时常量池方法引用 ;

每个 方法 都有一个对应的 " 栈帧 " , 在栈帧 内部 的 " 动态链接 " 中 , 包含了 " 运行时常量池 " 中 栈帧对应方法的引用 , 该操作的目的是支持当前 方法 能 实现 动态链接 ;

2、静态链接与动态链接

静态链接 :字节码文件加载到 Java 虚拟机内存后 , 如果在 编译阶段 就知道 目标方法 的 引用 , 并且在 运行时引用不变 , 那么调用方法时 , 直接使用 方法的符号引用 转为 直接引用 的过程 , 称为 静态链接 ;

动态链接 :编译阶段 , 无法确定 被调用的方法 , 只能在 运行时 将 方法符号引用 转为 直接引用 , 这种 动态的引用转换 , 称为 动态链接 ;

3、早期绑定 和 晚期绑定

方法绑定 分为 早期绑定 和 晚期绑定 ;

早期绑定 :被调用的方法在 编译期 可以知道 , 并且运行时保持不变 , 静态链接 ;

晚期绑定 :被调用的方法 在 编译期 无法确定 , 在运行时动态地绑定相关方法 , 动态链接 ;

4、动态链接示例

动态链接指的是 , 将 Java 源码编译为 class 字节码文件后 , 方法调用 如helloWorld.add(), 在 class 字节码文件中只是一个字符 , 在运行时 , 需要靠 " 动态链接 " 指向要运行的helloWorld.add()方法首地址 ;

" 动态链接 " 本质是 将 " 符号引用 " 转为 " 直接引用 " ;

在上述字节码 常量池 中 HelloWorld 类的 add 方法的引用如下 :

#4 = Methodref#2.#18 // HelloWorld.add:()I

#4 = Methodref指向了#2.#18, #18 就是 add 方法 ;

#18 = NameAndType #10:#11 // add:()I

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。