参考书籍:《深入理解java虚拟机》,三天时间用了八个小时看完,像读一本武侠小说,挺爽。

另外需声明:图片都是从我自己的csdn博客转载,所以虽然有csdn标识,但都是我自己画的图片。

java是半编译半解释的语言,.java首先编译为.class。通过一些二进制阅读软件,你可以去了解.class文件的内部构成。《深入理解java虚拟机》一书有专门章节讲这个,我觉得比较麻烦,不多说。

配合《深入理解java虚拟机》一书、类似这样的方式去了解.class文件里面的二进制信息,可以搞得很清楚(类信息怎样存、类成员变量怎样存、方法怎样存等等):

虚拟机类加载机制(java是半编译半解释的语言,.java文件首先编译为.class文件,由于编译是面向jvm的,所以这与C++的编译思路有些不同。只要编译为jvm能理解的就可以了,而非像C++那样编译为计算机可以执行的机器码。java的jvm才负责与真正的计算机交流,java程序则只需jvm能解读就可以了。所以这种半编译半解释的特性提供了很多C++所无法企及的灵活性。):

上图是java的加载机制。我们首先需要了解的是java类初始化(图中的Initialization)的时机(包括但不完全是这三种):

1,new

2,反射

3,初始化一个类时,若父类还未被初始化,先初始化其父类

而类的加载时机,则是最迟不晚于类的初始化时机。

类加载要做的事首先是通过类名(包括包),找到此类的.class二进制字节流。将该类信息加载到方法区(大抵仍是很原始的.class内容)。然后再内存中实例化一个java.lang.Class类对象(每一个类的信息在java中也是对象,这是很有哲学意味的一个概念)。这个java.lang.Class对象却并不是java堆中(虽然是对象),是存在方法区里。这个对象是程序访问方法区中类的对外接口。

在图中的的准备(Preparation)阶段,是对加载阶段的延续--同样是在方法区做事:初始化static变量。只分配内存空间,此时都是0值。

例如一个类中写到public static int value = 123; 则在准备阶段,publi static int value = 0;在初始化阶段才public static int value = 123;

但若为public static final int value = 123;则在准备阶段 便public static final int value = 123;

解析阶段是将常量池(《深入理解虚拟机》第六章介绍)内的符号引用(.class文件内的数据结构)转化为直接引用(真正对应虚拟机内存布局)

可以看出在初始化过程前,都是对类信息的加载、连接,也都是在方法区进行的。而从初始化阶段开始,真正涉及java执行引擎。

大致为下面这样的代码的话:

  1. public class C
  2. {
  3. private int b = ;
  4. public static int a;
  5. public method1(){……}
  6. }

java代码的执行主要基于栈结构(方法),而堆就是动态分配对象内存的地方,这些堆、栈的概念与C++相似。不同的是java是半解释型的语言。java程序是解释执行(之前的加载类信息过程也不仅仅是通过编译后的.class,可以通过jar包、网络、运行时计算生成例如动态代理、其它文件例如jsp)在jvm的执行引擎,而C++程序是直接执行在真实的计算机之上(编译为目标汇编后……)

这里引用一下《深入理解java虚拟机》中的一段话:

执行引擎是Java虚拟机最核心的组成部分之一。“虚拟机”是一个相对于“物理机”的概念。这两种机器都有代码执行的能力,其区别是物理机执行引擎是直接建立在处理器、硬件、指令集和操作系统层面上的,而虚拟机的执行引擎则是由自己实现的,因此可以自行制定指令集与执行引擎的结构体系,并且能够执行那些不被硬件直接支持的指令集格式。

我之前画过一张基于C++语言反汇编来分析的栈空间示意图,画的是开辟新栈帧的过程,图中有些顺序没法表示清楚,先是参数入栈,然后ebp入栈,之后ebp指向esp,sub esp新栈帧长度、然后push ebx、esi、edi、局部变量入栈。

退出当前栈帧的过程与之相反。pop edi ,pop esi , pop ebx ,mov esp,ebp ,pop ebp 。之后,edi,esi,ebx恢复原来状态,ebp指向上一个栈帧栈底,esp指向上一个栈帧栈顶:

java虚拟机的栈帧结构与之有些差异,因为这是虚拟机,而非物理机(首先就不会用到物理机那些寄存器)。

首先我们要知道一点,在.java文件编译为.class文件的时候,.class文件里便已经定义了许多栈帧需要的信息:例如一个栈帧需要多大局部变量表、多深的操作数栈等等。

图上所说的方法的符号引用和直接引用可以大致这样理解:符号引用只是说明要调用哪个方法,而直接引用则是指明了方法在虚拟机里的内存地址。

符号引用向直接引用的转化有两种:其一是解析阶段(见本文第一张图)。另一种是动态连接(运行时确定)。前者基本就是编译阶段确定了类型,后者则是运行时确定类型。

动态确定方法,就是要靠图中栈帧里的“动态连接”区域来搞定。

java的“反汇编”(注意我是打了引号的),由此可以看出虚拟机在栈中怎样解释执行java方法的,用的是java虚拟机独有的“指令集”:

java内功 ---- jvm虚拟机原理总结,侧重于虚拟机类加载执行系统的更多相关文章

  1. java中JVM的原理

    转载:https://blog.csdn.net/witsmakemen/article/details/28600127 一.java虚拟机的生命周期: Java虚拟机的生命周期 一个运行中的Jav ...

  2. java中JVM的原理重温【转】

    一.基础理论知识 1.java虚拟机的生命周期: Java虚拟机的生命周期 一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序.程序开始执行时他才运行,程序结束时他就停止.你在同一台机器上 ...

  3. JAVA和JVM运行原理揭秘

    这里和大家简单分享一下JAVA和JVM运行的原理,Java语言写的源程序通过Java编译器,编译成与平台无关的‘字节码程序’(.class文件,也就是0,1二进制程序),然后在OS之上的Java解释器 ...

  4. 【转】java中JVM的原理

    转载自https://blog.csdn.net/witsmakemen/article/details/28600127/ 一.java虚拟机的生命周期: Java虚拟机的生命周期 一个运行中的Ja ...

  5. java内功 ---- jvm虚拟机原理总结,侧重于GC

    写作日期 2016-08-22-23 交流qq:992591601 参考资料:<深入理解java虚拟机>.<thinking in java>.<Effective Ja ...

  6. JVM 内部原理(五)— 基本概念之 Java 虚拟机官方规范文档,第 7 版

    JVM 内部原理(五)- 基本概念之 Java 虚拟机官方规范文档,第 7 版 介绍 版本:Java SE 7 每位使用 Java 的程序员都知道 Java 字节码在 Java 运行时(JRE - J ...

  7. 《Java虚拟机原理图解》3、JVM执行时数据区

    [last updated :2014/11/7]     JVM执行时数据区(JVM Runtime Area)事实上就是指JVM在执行期间,其对计算机内存空间的划分和分配.本文将通过下面几个话题来 ...

  8. 《Java虚拟机原理图解》4.JVM机器指令集

    0. 前言 Java虚拟机和真实的计算机一样,执行的都是二进制的机器码:而我们将.java 源码编译成.class 文件,class文件便是Java虚拟机可以认识的二进制机器码,Java可以识别cla ...

  9. JAVA的JVM虚拟机工作原理.V.1.0.0

    注意:一下内容纯属个人理解,如有错误,欢迎批评指正. (90度弯腰)谢谢. java在JVM上的运行过程: 1,编辑好的java代码(IDE无报错,测试运行无错误): 2,java源代码通过javac ...

随机推荐

  1. 推荐有料哥:HR社保公积金状况大揭底

    昨天下午有料哥和几位三茅运营成员一起和大家进行三个小时的面对面,如潮的问题让几位三茅团队成员都措手不及了,有料哥也融入了大家紧张好奇问题的好奇,无奈水平有限不能很好回复,请大家谅解,有问题还可以在有料 ...

  2. 【转载】Java中的回车换行符/n /r /t

    source:http://hane00.blog.163.com/blog/static/1600615220126204446809/ '\r'是回车,'\n'是换行,前者使光标到行首,后者使光标 ...

  3. js常用的地址栏参数获取

    用JS获取地址栏参数的方法(超级简单) 方法一:采用正则表达式获取地址栏参数:( 强烈推荐,既实用又方便!) function GetQueryString(name) {      var reg ...

  4. php设计模式--单例模式

    单例模式(Singleton Pattern 单件模式或单元素模式) 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 单例模式是一种常见的设计模式,在计算机系统中,线程池.缓 ...

  5. java连接Oracle数据库

    Oracle数据库先创建一个表和添加一些数据 1.先在Oracle数据库中创建一个student表: create table student ( id ) not null primary key, ...

  6. 关于libsvm工具箱在64位matlab下的安装说明

    LIBSVM工具箱的安装 基本方法: 1.在网上下载LIBSVM工具箱. http://www.csie.ntu.edu.tw/~cjlin/libsvm/ 2.将LIBSVM工具箱所在目录添加到MA ...

  7. JavaScript-navigator_userAgent-编写一段代码能够区分浏览器的主流和区分

    1 userAgent:包含浏览器名称和版本号的字符串 <!DOCTYPE html> <html> <head lang="en"> < ...

  8. JS无刷新分页插件

    本文介绍一个本人自己写的一JS分页插件 <script src="/Js/smart.page.min.js" type="text/javascript" ...

  9. C# GetHashCode与Equals在HashTable表查找时的关系

    using System; using System.Collections.Generic; using System.Text; using Microsoft.Win32; using Syst ...

  10. <Oracle Database>后台进程

    进程监视器进程(PMON)  这个进程负责在出现异常中止的连接之后完成清理.PMON会回滚未提交的工作,并释放为失败进程分配的SGA资源.PMON还负责监视其他的Oracle后台进程,并在必要时(如果 ...