深入理解JVM内部结构(转)
- boolean
- byte
- char
- long
- short
- int
- float
- double
- reference
- returnAddress
除了long和double,所有的类型都在局部变量数组中占据一个位置,long及double则占用两个连续的位置(slot),由于它们是双倍的宽度,也即64位大小。
- int i;
编译以后的字节码如下:
- 0: iconst_0 // Push 0 to top of the operand stack
- 1: istore_1 // Pop value from top of operand stack and store as local variable 1
- Young Generation(年轻代),通常被分为Eden和Survivor
- Old Generation(老年代,也叫Tenured Generation)
- Permanent Generation
(2) 内存管理
- 类加载器引用
- 运行时常量池
- 数值常量
- 字段引用
- 方法引用
- 属性值
- 字段数据
- 每个字段
- 名称
- 类型
- Modifiers
- 属性值
- 每个字段
- 方法数据
- 每个方法
- 名称
- 返回类型
- 参数类型
- Modifiers
- 属性值
- 每个方法
- 方法代码
- 每个方法
- 字节码
- 操作对象栈大小
- 局部变量大小
- 局部变量表
- 异常表
- 每个异常处理器
- 起始点
- 结束点
- 处理器代码的PC偏移值
- 捕抓的异常类的常量池索引
- 每个异常处理器
- 每个方法
所有的线程共享相同的方法区,因此方法区数据的存取及动态链接的过程必须是线程安全的。如果两个线程都企图存取同一个类中的字段或方法,但是,此类还没有被加载,则它必须只被加载一次,并且线程必须等到类被加载完成以后才能继续执行。
- ClassFile {
- u4 magic;
- u2 minor_version;
- u2 major_version;
- u2 constant_pool_count;
- cp_info contant_pool[constant_pool_count – 1];
- u2 access_flags;
- u2 this_class;
- u2 super_class;
- u2 interfaces_count;
- u2 interfaces[interfaces_count];
- u2 fields_count;
- field_info fields[fields_count];
- u2 methods_count;
- method_info methods[methods_count];
- u2 attributes_count;
- attribute_info attributes[attributes_count];
- }
如果你想看一个编译完成的类文件的字节码,可以使用命令行工具javap。
- package org.jvminternals;
- public class SimpleClass {
- public void sayHello() {
- System.out.println("Hello");
- }
- }
- public class org.jvminternals.SimpleClass
- SourceFile: "SimpleClass.java"
- minor version: 0
- major version: 51
- flags: ACC_PUBLIC, ACC_SUPER
- Constant pool:
- #1 = Methodref #6.#17 // java/lang/Object."<init>":()V
- #2 = Fieldref #18.#19 // java/lang/System.out:Ljava/io/PrintStream;
- #3 = String #20 // "Hello"
- #4 = Methodref #21.#22 // java/io/PrintStream.println:(Ljava/lang/String;)V
- #5 = Class #23 // org/jvminternals/SimpleClass
- #6 = Class #24 // java/lang/Object
- #7 = Utf8 <init>
- #8 = Utf8 ()V
- #9 = Utf8 Code
- #10 = Utf8 LineNumberTable
- #11 = Utf8 LocalVariableTable
- #12 = Utf8 this
- #13 = Utf8 Lorg/jvminternals/SimpleClass;
- #14 = Utf8 sayHello
- #15 = Utf8 SourceFile
- #16 = Utf8 SimpleClass.java
- #17 = NameAndType #7:#8 // "<init>":()V
- #18 = Class #25 // java/lang/System
- #19 = NameAndType #26:#27 // out:Ljava/io/PrintStream;
- #20 = Utf8 Hello
- #21 = Class #28 // java/io/PrintStream
- #22 = NameAndType #29:#30 // println:(Ljava/lang/String;)V
- #23 = Utf8 org/jvminternals/SimpleClass
- #24 = Utf8 java/lang/Object
- #25 = Utf8 java/lang/System
- #26 = Utf8 out
- #27 = Utf8 Ljava/io/PrintStream;
- #28 = Utf8 java/io/PrintStream
- #29 = Utf8 println
- #30 = Utf8 (Ljava/lang/String;)V
- {
- public org.jvminternals.SimpleClass();
- Signature: ()V
- 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 3: 0
- LocalVariableTable:
- Start Length Slot Name Signature
- 0 5 0 this Lorg/jvminternals/SimpleClass;
- public void sayHello();
- Signature: ()V
- flags: ACC_PUBLIC
- Code:
- stack=2, locals=1, args_size=1
- 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
- 3: ldc #3 // String "Hello"
- 5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
- 8: return
- LineNumberTable:
- line 6: 0
- line 7: 8
- LocalVariableTable:
- Start Length Slot Name Signature
- 0 9 0 this Lorg/jvminternals/SimpleClass;
- }
- 常量池, 它提供了与符号表相同的信息,这个将在后面进行详述。
- 方法, 每个方法包含了四个部分:
- 签名及访问标记
- 字节码
- 行号表, 它主要用于为调试器提供信息,行号表指示了每个字节码指令对应的行数,如Java代码中的第六行对应了sayHello方法中的字节码0,第七行对应了字节码8.
- 局部变量表, 它列出了帧中提供的所有局部变量,在本例子中,只有this这一个局部变量。
此类文件中使用到的字节码操作数有:
|
aload_0
|
此操作码是格式为aload_<n>的操作码组的成员之一,它们都是用于加载一个对象引用到操作
对象栈中. <n>指示了对象在局部变量数组中的位置,可选的数字只能是0,1,2,3之一。还有其它类似的操作
码用于加载数值,而非对象引用。如iload_<n>,lload_<n>, fload_<n>和dload_<n>,其中i是指int类型
l是long,f是float,d是double类型。对于索引值超过3的局部变量,可以使用iload,lload,fload,dload进行
加载。这些操作码都只有一个操作数,用于指定要加载的局部变量的索引。
|
|
ldc
|
这个指令(操作码)用于将一个运行时常量池中的常量压入操作对象栈中
|
|
getstatic
|
此指令用于将运行时常量池的静态字段列表中的一个静态值压入到操作对象栈中。
|
|
invokespecial,
invokevirtual
|
这两个指令属于调用方法的指令组成员之一,调用方法的指令有:invokedynamic,invokestatic,
invokevirtual。在这个类文件中,invokevirtual用于基于对象的类进行方法调用,而invokespecial指令则用
于调用当前类的实例初始化方法,私有方法及父类方法。
|
|
return
|
此指令时返回型指令组成员之一,其它的还有ireturn,lreturn,freturn,dreturn,areturn及
return。每个指令都是一类返回不同类型数值的返回声明,i是int类型,l是long,f是float,d是
double,a则是对象引用。没有前置类型字符的return则是返回void类型。
|




- 数值型字面值
- 字符串字面值
- 类引用
- 字段引用
- 方法引用
如下面的代码:
- Object foo = new Object();
其对应的字节码如下:
- 0: new #2 // Class java/lang/Object
- 1: dup
- 2: invokespecial #3 // Method java/ lang/Object "<init>"( ) V
- 起始点
- 结束点
- 处理器代码的PC偏移值
- 被捕抓的异常类的常量池索引
如果一个方法定义了一个try-catch或try-finally异常处理器,则一个异常表将会被创建。异常表包含了每个异常处理器或者是finally块的信息,如异常处理应用的范围,那种类型的异常会被处理及异常处理代码所在的位置。
转载地址:http://blog.csdn.net/huaishu/article/details/9844257
深入理解JVM内部结构(转)的更多相关文章
- 深入理解JVM内幕(转)
转自:http://blog.csdn.net/zhoudaxia/article/details/26454421/ 每个Java开发者都知道Java字节码是执行在JRE((Java Runtime ...
- 深入理解JVM内幕:从基本结构到Java 7新特性
转自:http://www.importnew.com/1486.html 每个Java开发者都知道Java字节码是执行在JRE((Java Runtime Environment Java运行时环境 ...
- [译]深入理解JVM
深入理解JVM 原文链接:http://www.cubrid.org/blog/dev-platform/understanding-jvm-internals 每个使用Java的开发者都知道Java ...
- 转:深入理解jvm
深入理解JVM 原文链接:http://www.cubrid.org/blog/dev-platform/understanding-jvm-internals 每个使用Java的开发者都知道Java ...
- 【转】[译]深入理解JVM
http://www.cnblogs.com/enjiex/p/5079338.html 深入理解JVM 原文链接:http://www.cubrid.org/blog/dev-platform/un ...
- 深入理解JVM内幕:从基本结构到Java 7新特性[转]
英文原文:cubrid,编译:ImportNew - 朱伟杰 译文链接:http://www.importnew.com/1486.html [如需转载,请在正文中标注并保留原文链接.译文链接和译者等 ...
- 深入理解 JVM 的内存区域
深入理解运行时数据区 代码示例: 1. JVM 向操作系统申请内存: JVM 第一步就是通过配置参数或者默认配置参数向操作系统申请内存空间,根据内存大小找到具体的内存分配表,然后把内存段的起始地址和终 ...
- 深入理解JVM垃圾收集机制(JDK1.8)
垃圾收集算法 标记-清除算法 最基础的收集算法是"标记-清除"(Mark-Sweep)算法,分两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象. 不足: ...
- 深入理解JVM(一)编译openJDK
此文总结的很不错:https://www.cnblogs.com/ACFLOOD/p/5528035.html 准备openJDK源码和环境 1.在linux和macOS上编译openJDK更加友好, ...
随机推荐
- php变量与数组相互转换的方法(extract与compact
#php变量与数组相互转换的方法(extract与compact) #compact 多个变量转数组 $name = 'sui'; $email = 'sui@qq.com'; $arr = comp ...
- BZOJ2621 [Usaco2012 Mar]Cows in a Skyscraper
首先比较容易想到是状态压缩DP 令$f[S]$表示选取了集合$S$以后,已经送了最少次数$cnt$且当前电梯剩下的体积$rest$最大(即$f[S]$是一个二元组$(cnt, rest)$) 于是$f ...
- 用户上网的基本流程图与DNS解析原理
1.用户上网发送请求,首先确认本地的hosts中是否含有域名,有则进行ip访问,如果没有呢?看本机的display缓存中有没有访问网站的ip,有就直接去访问 那么如果本地的hosts和缓存都没有呢?这 ...
- java面向对象编程——第五章 对象的行为
5.1 方法调用栈 当一个方法被调用时,将导致控制流程跳转到被调用的方法.然后,控制流程执行方法中的语句.当然,被执行的方法可能会调用其它方法,导致控制流程跳转到其它方法.所有的方法调用都维护在一个称 ...
- 第三方开源框架的下拉刷新列表(QQ比较常用的)。
PullToRefreshListView是第三方开源框架下拉刷新列表,比较流行的QQ 微信等上面都在用. 下载地址(此开源框架于2013年后不再更新) 点此下载 package com.lixu.k ...
- 一模 (5) day1
第一题: 题目大意:求出1-10^n 这些数中,包含数字3的有多少个. n<=1000: 解题过程: 1.这题一看就是高精度+递推..如果n=1000,那么假设个位是3,其他999位任意..那么 ...
- 从报错“无效操作,连接被关闭”探究Transaction的Timeout超时机制
1.报错如下:Invalid Operation the connection is closed,无效操作,连接被关闭.这个错误是并不是每次都报,只有在复杂操作.大事务的情况下才偶然报出来. sta ...
- Format a Hard Drive in Csharp C#格式化总结
using System; using System.Diagnostics; using System.IO; using System.Linq; using System.Management; ...
- 《day16_多线程细节_Eclipse使用》
多线程的一些细节: 1,面试题:sleep方法和wait方法异同点是什么? 相同点:可以让线程处于冻结状态. 不同点: 1, sleep必须指定时间. wait可以指定时间,也可以不指定时间. 2, ...
- golang vim环境搭建
主要使用到的是golang的vim插件vim-go, 安装方法: (1)配置好自己的GOPATH和GOROOT: (2)在GOPATH目录下建立 src.pkg.main.bin四个目录: (3)安装 ...