深刻理解java虚拟机之虚拟机执行子系统笔记

一个多月来浑浑噩噩,有时看电视打游戏,有时听听歌看看书逛逛街,有时闲谈扯淡,有时静坐思过,有时炒几个小菜还有时发呆半晌。或喜或忧,以思无益,不如学也。html

每一个java类经编译以后生成一个Class字节码文件,Class文件具备固定的文件存储格式。虚拟机把Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终造成能够被虚拟机直接使用的java类型。java

Class文件结构(略)程序员

C语言编程机制编程

C编程的基本机制:编译、连接。这使得程序便于模块化。您能够分别编译各个模块,而后用连接器将编译过的模块结合起来。数组

编译:将高级语言翻译成低级语言的过程。(C语言中生成目标代码)数据结构

连接:将目标代码、引用的库代码以及启动代码结合在一块儿,并把它们存放在单个文件中,即生成可执行文件。jvm

库代码:C语言(标准)库函数模块化

启动代码:程序和操做系统间的接口
函数

类加载过程post

 

加载(完成三件事):

①.经过类的全限定名来获取定义此类的二进制字节流

②.将这个字节流的静态储存结构转换为方法区的运行时数据结构

③.在java堆中生成一个表明这个类的java.lang.Class对象,做为方法区这些数据的访问入口。

链接:

验证:检查Class字节码文件是否符合当前虚拟机规范

准备:为类变量分配内存并设置类变量的默认值(注意:常量在准备阶段将被赋予程序员指定初始值)

解析:将常量池中的符号引用替换为直接引用,即判断类和接口、属性、类方法和接口方法是否有效、是否具有访问权限等。

(类)初始化:执行类构造器<clinit>方法的过程。对类变量和静态语句块赋予程序员定制的值。

关于<clinit>与<init>

 

<clinit>:类构造器。初始化阶段,java编译器自动收集类变量与静态语句块的初始化语句(按先变量赋值再静态语句块的绝对顺序,所以在静态语句块中能够访问到类变量的初始值),放在<clinit>方法中。虚拟机保证子类的<clinit>方法执行以前父类的<clinit>方法已经执行完毕。所以虚拟机中第一个被执行的<clinit>()方法的类确定是java.lang.Object

<init>:实例构造器。对象初始化时,jvm会调用<init>()方法为实例变量和初始化块进行初始化(而后才是构造方法)。<init>会显示的调用父类的构造器。

参考:http://www.ibm.com/developerworks/cn/java/j-lo-clobj-init/index.html

  http://penny.iteye.com/blog/83604

实例化一个类(生成对象)有四种途径:

调用new操做符;

调用Class或java.lang.reflect.Constructor对象的newInstance()方法;

调用任何现有对象的clone()方法;

经过java.io.ObjectInputStream类的getObject()方法反序列化。

(类)初始化时机:虚拟机规范严格规定有且只有四种状况必须当即对类进行初始化:

①.遇到new、getstatic、putstatic或invokestatic这4条字节码指令时,若是类没有初始化,则须要出发其初始化。(注意:特殊状况,全局常量在准备阶段初始化)

②.使用java.lang.reflect包的方法对类进行反射调用时

③.当初始化一个类,若是发现其父类没有初始化,则须要先触发其父类的初始化

④.当虚拟机启动时,用户须要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类

类加载器

参考: http://www.ibm.com/developerworks/cn/java/j-lo-classloader/

虚拟机字节码执行引擎(基于栈的解释执行)

参考:

JVM工做原理和特色  http://developer.51cto.com/art/200907/135143.htm

《深刻java虚拟机》sun公司核心技术丛书 (美)Bill Venners著 曹小钢 蒋靖 译

虚拟机栈是线程独享的,每当启动一个新线程时,JVM都会为它分配一个java栈。java栈以帧为单位保存线程的运行状态。虚拟机只会对java栈执行两种操做:以帧为单位的压栈和出栈。每个栈帧都包括三部分:局部变量表、操做数栈、帧数据区。

局部变量表是一组变量值储存空间,用于存放方法参数和方法内部定义的局部变量。它被组织为一个以字长(32位)为单位、从0开始计数的数组,其中第0位索引默认是用于传递所属对象实例的引用,在方法中能够经过关键字“this”来访问该隐含的参数。

操做数栈被组织为一个以字长为单位(数组实现)的栈。

Java虚拟机没有寄存器,Java虚拟机的指令是从操做数栈中取得操做数而不是从寄存器中取得操做数,所以JVM是基于栈运行而不是基于寄存器运行的。

参考: http://blog.csdn.net/tuhuolong/article/details/6458815

若是读者有兴趣能够参考《深刻理解Java虚拟机》 周志明:P224 配图说明基于栈的解释器质性过程,能够对比下汇编语言。

实战

书中提到:Java程序社区中流传着这么一个观点:“学习JavaEE规范,去看Jboss源码;学习类加载器,就去看OSGi源码”。感兴趣能够探究。

转载于:https://www.cnblogs.com/zhangpeng201211/archive/2012/08/16/2642980.html