深入解析java虚拟机-jvm运行机制
一:JVM基础概念
JVM(Java虚拟机)一种用于计算设备的规范,可用不同的方式(软件或硬件)加以实现。编译虚拟机的指令集与编译微处理器的指令集非常类似。Java虚拟机包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。
Java虚拟机(JVM)是可运行Java代码的假想计算机。只要根据JVM规格描述将解释器移植到特定的计算机上,就能保证经过编译的任何Java代码能够在该系统上运行。
带着几个问题我们来阅读下面的文章,希望能够对jvm运行机制不是很清楚的朋友有一点点的帮助。如果对jvm运行机制非常了解可以留言 提下意见和你认为不对的地方。
- jvm是怎么运行的?
- jvm运行时内存是怎么分配的?
- jvm每个区在jvm体系中都充当着什么角色?
- java文件里面的代码最终都存储在jvm的那些区?
二:JVM体系结构
Java虚拟机,java源文件(.java)通过编译器生成字节码文件(.class),字节码文件(.class)通过JVM(Java虚拟机)中的解释器再翻译成特定机器上的机器码。
编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由解释器来将虚拟机代码转换为特定系统的机器码执行。每一种平台的解释器是不同的,但是实现的虚拟机是相同的。当一个程序从开始运行一个程序,这时虚拟机就开始实例化了。多个程序启动就会存在多个虚拟机实例。程序退出或者关闭。则虚拟机实例消亡。多个虚拟机实例之间数据不能共享。
如下图所示,JVM的体系结构包含几个主要的子系统和内存区:
- 垃圾回收器(Garbage Collection):负责回收堆内存(Heap)中没有被使用的对象,即这些对象已经没有被引用了。
- 类装载子系统(Classloader Sub-System):除了要定位和导入二进制class文件外,还必须负责验证被导入类的正确性,为类变量分配并初始化内存,以及帮助解析符号引用。
- 执行引擎(Execution Engine):负责执行那些包含在被装载类的方法中的指令。
- 运行时数据区(Java Memory Allocation Area):又叫虚拟机内存或者Java内存,虚拟机运行时需要从整个计算机内存划分一块内存区域存储jvm需要用到的东西。而这个运行时数据区里面又会分为许多的小区。每个区都有自己不同的职责。后面会讲到每个区的作用和存储的内容。
三:jvm运行时数据区
- 程序计数器 (Program Counter Register):
是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的方式去实 现),字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。
如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Natvie方法,这个计数器值则为空(Undefined)。此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
- 栈 (stack):
这块区域是线程私有的,它的生命周期和和线程一样。在jvm中。每个方法执行的时候jvm都会创建一个栈帧。用来存储局部变量、操作栈、动态栈和方法返回等信息。每一个方法从调用到结束对应着一个栈帧在虚拟机里面的入栈和出栈。
栈里面存储了编译器已知的八种基本数据类型,String不在里面。后面会对String类型进行详细的介绍。(boolean、char、double、int、long、byte、float、short)。
在用java关键字 new 一个对象时。比如(ControllerHelper helper = new ControllerHelper ())时。stack内存中存储的是一个helper栈帧地址引用。其地址指向的是heap中的内存区域。如下图:
注意: 存Heap地址引用只对于sun 公司的虚拟机<HotSpot>。其他公司的可能会不一样。存的可能是句柄。
- 本地方法区 (Native Method Area)
这块区域在jvm运行内存中职责就相对比较少了。只是执行Native 方法。如果这个区的内存不足也是会抛出StackOverflowError 和 OutOfMemoryError 异常。
- 堆 (Heap)
这块区域可以说是jvm中最大的一块区域了。几乎所有的对象和数据都是存在这个区域。这块区域也是线程共享的。也是 gc 主要的回收区。可以从我第一个图看出Heap区中还可以分为新生代(Young Generation)和老年代(Old Generation)。gc每隔一段时间就会对新生代进行垃圾回收。在分配对象遇到内存不足时,先对新生代进行GC(Young GC);当新生代GC之后仍无法满足内存空间分配需求时, 才会对整个堆空间以及方法区进行GC(Full GC)。而新生代又可以分为一个Eden空间和两个Survivor
(From Survivor 和 To Survivor ) 空间。新生代中的E区和S区又有不同的职责。
E区:gc 触发比较频繁的区域。存储的是新new的对象。几乎所有的对象都会经过E区。如果gc过后对象还没死亡就会把未死亡的对象存储到S区。
S区:Survivor 区作为Eden区和old(老年代)的缓存。它是可以向老年代转移活动对象的实例。
java 堆它在屋里内存上可以是不连续的内存空间。只要是逻辑上是连续的就可以了。查看程序新生代、老年代信息可以执行命令 jstat -gcutil 6912 500
- 方法区 (Method Area)
方法区和堆一样也是线程共享的区域,它主要是存储被虚拟机加载的类信息、常量、静态变量、及时编译器编译后的代码等数据。它不属于Heap区域中的一部分。对于sun公司的HotSpot虚拟机来说。gc也会对这块区域进行垃圾回收。但是对于heap的垃圾回收而已。这块区域垃圾回收比较少。String str=”is string”。str就是存在方法区。Sample.class.getSimpleName() 方法就是从方法区中区得的结果。
如果细分方法区还可以细分为运行常量池 (Runtime Constant Pool) 。它主要存储class文件中的版本、字段、方法、接口等描述信息。运行常量池还可以分为信息常量池 (Constant Pool Table)。它主要是存储编译器生成的各种字面量和符号引用。
并不是所有的常量都只能在编译期产生。对于String类型的 intern( )方法就可以在运行时把变量存入方法区。当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。
深入解析java虚拟机-jvm运行机制的更多相关文章
- JVM学习001通过实例总结Java虚拟机的运行机制
JVM学习(1)——通过实例总结Java虚拟机的运行机制-转载http://www.cnblogs.com/kubixuesheng/p/5199200.html 文章转载自:http://www.c ...
- JVM学习(1)——通过实例总结Java虚拟机的运行机制
俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及到的知识点总结如下: JVM的历史 JVM的运行流程简介 JVM的组成(基于 Java 7) JVM调优参数:-Xmx和-Xms ...
- JVM学习(1)——通过实例总结Java虚拟机的运行机制(转)
俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及到的知识点总结如下: JVM的历史 JVM的运行流程简介 JVM的组成(基于 Java 7) JVM调优参数:-Xmx和-Xms ...
- JVM学习(1)——通过实例总结Java虚拟机的运行机制-转载http://www.cnblogs.com/kubixuesheng/p/5199200.html
JVM系类的文章全部转载自:http://www.cnblogs.com/kubixuesheng/p/5199200.html 特别在此声明.那位博主写的真的很好 ,感谢!! 俗话说,自己写的代码, ...
- 深入理解Java虚拟机-JVM运行时数据区域
一.运行时数据区域 1.程序计数器 程序计数器( Program Counter Register) 是一块较小的内存空间, 它可以看作是当前线程所执行的字节码的行号指示器. Java虚拟机的多线程是 ...
- Java虚拟机JVM学习07 类的卸载机制
Java虚拟机JVM学习07 类的卸载机制 类的生命周期 当Sample类被加载.连接和初始化后,它的生命周期就开始了. 当代表Sample类的Class对象不再被引用,即不可触及时,Class对象就 ...
- Java虚拟机JVM学习05 类加载器的父委托机制
Java虚拟机JVM学习05 类加载器的父委托机制 类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap ...
- Java虚拟机JVM学习03 连接过程:验证、准备、解析
Java虚拟机JVM学习03 连接过程:验证.准备.解析 类被加载后,就进入连接阶段. 连接就是将已经读入到内存的类的二进制数据合并到虚拟机的运行时环境中去. 连接阶段三个步骤:验证.准备和解析. 类 ...
- Java Jvm运行机制原理
一:简介 在学习Java虚拟机之前,也就是Jvm之前,我想大家能够带着问题去学习,这样的话,大家学习起来也会比较有所获! 1.Java虚拟机(Jvm)是什么? 2.Java虚拟机是用来干什么的? 3. ...
随机推荐
- Java基础知识强化之IO流笔记40:字符流缓冲流之特殊功能 [ newLine() / readLine() ]
1. 字符缓冲流的特殊方法 BufferedWriter: public void newLine():根据系统来决定换行符 BufferedReader: public String readLin ...
- Android应用程序所包含的四种组件和DDMS
关注用户组件 Activity 编辑文本 .玩游戏 后台进程 Service ...
- [Form Builder]NAME_IN()与COPY()
NAME_IN和COPY实际是间接引用,类似指针传递,而不是值传递... IF :VAR1 IS NULL ... direct referenceIF NAME_IN ( :VAR1 ) IS N ...
- Linux基础命令(三)
一.常用命令—文件目录类命令 1.ls 列出指定或默认目录的文件信息 使用形式: ls [选项] [目录名] 实例: $ls $ls –als $ls /home/sq/Desktop $ls ./D ...
- readonly和const区别
常量和只读变量的区别 const string name="Xuj"; readonly string name; 1.常量是不可改变的,只读变量只能在构造方法中才能改变其值. 2 ...
- 20160410javaweb之JDBC---DBUtils框架
DBUtils 1.DbUtils 工具类 2.QueryRunner -- 两行代码搞定增删改查 (1)QueryRunner() --需要控制事务时,使用这组方法 int update(Conne ...
- Android SDK目录含义介绍
Android SDK目录的具体结构: 1.add-ons:该目录下存放第三方公司为Android平台开发的附加功能系统. 2.build-tools:编译工具.保存着一些通用工具,比如aapt.ai ...
- Android在onCreate()中获得控件尺寸
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceSt ...
- (五)Hibernate 操作对象
所有项目导入对应的hibernate的jar包.mysql的jar包和添加每次都需要用到的HibernateUtil.java 第一节:Hibernate 中四种对象状态 临时状态(transient ...
- swift之元组类型
一.元组类型是有N个任意类型的数据组成(N>=0),组成元组类型的数据可以称为“元素” 二.元组的定义 如:let position = (x:10.5,y:20) //两个元素的元组 l ...