Inside the Java Virtual Machine 读书笔记一

what?

说jvm,可能指的是:

  • the abstract specification,
  • a concrete implementation, or
  • a runtime instance.

一个运行时的虚拟机实例( a runtime instance)就是负责运行一个java程序,这个实例随着java程序的开始(main方法运行)而产生,结束而消失。

java虚拟机中有两种线程,守护线程与非守护线程,像gc这种后台线程就是守护线程,而main方法产生的是非守护线程。当所有的非守护线程结束,则jvm结束。

JVM(此处指:the abstract specification)定义了抽象的组成部分,以及它们之间的交互方式,来定义JVM的实现(a concrete implementation):

每个JVM都有一个 class loader subsystem,当类或接口(必须完全限定名)装载到JVM中,会被装载到class loader subsystem中.同样,每个JVM会有一个execution engine,负责执行载入的class中方法指令。

.Class文件与byteCode(字节码)

Class文件包含有代码以及支持代码用的元数据(metadata)。代码部分就是字节码,而元数据部分则包括诸如泛型等许多信息。所以说Class文件包含字节码,但不只有字节码。

Class Loader subclass

takes care of finding and loading types

jvm有两种类装载器:a primordial class loader and class loader objects(原始类装载器:jvm的一部分,用户自定义的类装载器对象:java程序的一部分 )。对于类装载器对象(java程序)都必须继承自

java.lang.ClassLoader.ClassLoader中定义的接口方法,提供了对JVM访问的机制。对于JVM中每个被装载的类型,都会产生一个java.lang.class对象代表它,和其他Object对象一样,对象的产生都在Heap中,而类型信息都放在Method Area.

类装载器除了要定位、导入二进制Class文件外,还必须验证导入类的正确性,为类变量分配并初始化内存

大致顺序:

  1. Loading: finding and importing the binary data for a type
  2. Linking: performing verification, preparation, and (optionally) resolution

    a. Verification: ensuring the correctness of the imported type

    b. Preparation: allocating memory for class variables and initializing the memory to default

    values

    c. Resolution: transforming symbolic references from the type into direct references.

  3. Initialization: invoking Java code that initializes class variables to their proper starting values.

runtime data areas

当JVM运行时,它需要内存去存储,比如字节码等其他从class文件中获取的信息,对象实例化,方法参数,返回值,局部变量,计算结果的媒介等等。于是每个JVM定义了多个 runtime data areas 去组织这些执行程序需要的内存。(各种JVM会根据这些抽象的定义,产生各种不同的具体实现)。

Method Area && Heap

每个JVM实例有一个Method Area 和一个Heap,这个MethodArea 、Heap被这个JVM中的所有线程所共享。当一个JVM使用classLoader正确定位并装载了class 文件,它会从这些二进制信息中解析出类型信息,并把这些类型信息放入MethodArea中,并把其中的对象实例放入Heap中。

我说了method area主要放类型信息,所谓类型信息指:

Type Information

For each type it loads, a Java Virtual Machine must store the following kinds of information in the

method area:

  • The fully qualified name of the type
  • The fully qualified name of the typeís direct superclass (unless the type is an interface or class java.lang.Object, neither of which have a superclass)
  • Whether or not the type is a class or an interface
  • The typeís modifiers ( some subset of` public, abstract, final)
  • An ordered list of the fully qualified names of any direct superinterfaces

其实通过java.lang.Class的方法,我们可以动态的获取存储在MethodArea里的一些类型信息:

public String getName();
public Class getSuperClass();
public boolean isInterface();
public Class[] getInterfaces();
public ClassLoader getClassLoader()

另外,MethodArea还包括这些:

  • The constant pool for the type

    每个Type(类或接口)都有一个constant pool。它是一个有序集合,其中存放基本类型的引用,还有类型(类或接口)的引用、类变量引用、方法引用。

  • Field information

    存储 类变量的信息:类变量的类型、名称、修饰符(如private、public 、final、static等等)

  • Method information

    方法名、方法返回值、方法修饰符号、方法参数列表、还有方法的字节码、方法抛出的异常列表(非abstract 、native 方法)。

  • All class ( Static Fields) variables declared in the type, except constants
  • A reference to class ClassLoader

    JVM需要追踪类型(type,指类或接口)是否被载入原始classLoader或classLoader的对象,因此method Area需要存储一个classloader的引用。

  • A reference to class Class

    JVM对每个载入的类型(interface\class)都会创建一个java.lang.class的实例。并且,JVM还要用某种方式,将这个java.lang.class实例与它的Type Information(存在与MethodArea) 关联起来。

    通过这个静态方法,你可以获取任何载入到classLoader里的类型对应的java.lang.class实例。

public static Class forName(String className)

另外一种方法获取class,是每个类型实例的getClass()方法。

        System.out.println(Class.forName("java.lang.String"));
        System.out.println(new String().getClass());

When the Java Virtual Machine loads a type, it uses a class loader to

locate the appropriate class file. The class loader reads in the class

file–a linear stream of binary data– and passes it to the virtual

machine. The virtual machine extracts information about the type from

the binary data and stores the information in the method area. Memory

for class (static) variables declared in the class is also taken from

the method area

如图:

用一个实例来描述一下JVM的动作:

class Lava {
    private int speed = 5; // 5 kilometers per hour

    void flow() {
    }
}

public class Volcano {
    public static void main(String[] args) {
        Lava lava = new Lava();
        lava.flow();
    }
}

运行程序,JVM找到并读取Volcano.class文件,然后在引入的Volcano.class文件中读取Volcano类的信息,将这些信息放入Method Area中。然后JVM通过解释Method Area中的codeByte调用main方法。

注意,当JVM执行main()时,它并没有加载Lava.class,它会按需加载。

执行main()时, JVM调用足够的内存空间给CostantPool的第一条Volcano类,然后在Volcano的ConstantPool中找类Lava的引用符号(就是字符“Lava”),它会检查Lava是否被载入。当JVM发现没有,就会寻找并读取Lava.class文件,然后从二进制的Lava.class中读取信息,并放入MethodArea.紧接着, JVM会把刚才ConstantPool的首条的指针(指向Volcano的指针)替换为指向方法区Lava类数据的指针,以后用这个指针快速访问Lava。

接下来,JVM通过ConstantPool的首条指针(指向MethodArea的Lava信息),来快速获取Lava信息,并按需分配足够内存。

(JVM总是通过MethodArea类型信息去判断需要调用多少内存)当JVM确定了内存大小,就去堆上分配,并把这个对象的speed变量初始化为0.然后,把生成的Lava对象的引用压入栈中。

Lava lava = new Lava();这个代码完成了。

然后,调用flow()。

数据类型

JVM通过在多种类型的数据上进行操作来完成计算。

基本类型保存值、引用类型指向对象。(基本类型与引用类型的区别,很简单)

这里要提boolean,虽然它也被定义为基本类型,但是java编译器把源码编译为字节码,装载在JVM中,boolean被用int或byte来表示,0表示false;非0整数被表示true.

Heap

Heap用来存放实例化对象或数组,会调用分配来自heap的内存空间。也就是说,对象本身(memory)在heap上创建。

两个Java application 不可能共享Heap,当一个java application 的不同线程可以共享,因此,我们在多线程中,同步的使用一个对象。

另外,代码中可以去决定什么时候创建对象,但是不能决定什么时候销毁对象(释放内存)。这个完全有JVM自己决定(GC管理heap,除了释放空间,它还会移动对象来减少内存碎片)。

我们已经知道,栈中存放执行堆中对象的引用,除此,堆中对象内部还会保留一个执行方法区的引用(为了快速访问类型信息)。

对于heap的两种实现:

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-10 23:45:57

Inside the Java Virtual Machine 读书笔记一的相关文章

maven 笔记:maven Could not create the Java Virtual Machine

1.安装好maven,在cmd中运行mvn –v,报错:"maven  Could not create the Java Virtual Machine" 2.分析:这是跟jvm有关,在cmd中运行 java –version,发现正常 3.继续分析:在安装maven的时候做了环境变量的配置: M2E_HOME : E:\liberary\maven Path : %M2E_HOME%\bin;(在Path变量末尾加上) MAVEN_OPTS: -Xms128m -Xmx512m 设

《深入理解Java虚拟机》读书笔记---第二章 Java内存区域与内存溢出异常

Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来.这一章就是给大家介绍Java虚拟机内存的各个区域,讲解这些区域的作用,服务对象以及其中可能产生的问题. 1.运行时数据区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域. 1.1程序计数器 程序计数器(Program Counter Register)是一块较小的内存空间,它的作用可以看作是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型中里,字

《深入理解Java虚拟机》读书笔记---第一章 走进Java

一.为什么要读此书 <深入理解Java虚拟机>这本书读了很多次,每次读都会有不一样的感受.首先说一下为什么要读这本书,如果把Java比喻成乾坤大挪移,那了解虚拟机的工作原理就是练习九阳神功,java语言是招式,对虚拟机的认识是内功心法,只有内功心法强大,所使的招式才强大,这就是为什么阳顶天只能把乾坤大挪移练到第四层,而张无忌能练到第七层.由于java虚拟机的强大,把很多功能都隐藏了,例如内容管理,垃圾回收机制等,使得很多java程序猿对这一块的知识所有缺失,编码的时候也是似懂非懂的,以至于遇到

Eclipse failed to create the Java Virtual Machine问题解决

1.问题描述 如标题所示,在开启Eclipse的时候,出现这个问题,以前是不曾出现过的问题,很奇怪: 2.问题解析 Failed to create the Java Virtual Machine,翻译过来的意思是,无法创建java虚拟机. 看到这样的问题,首先想到的是两个问题,第一,是否有文件缺失,导致虚拟机无法启动.想想不是太可能,文件缺失的话,应该之前就无法启动:再考虑是否有文件被安全软件回收了(360老干这种事情),打开360似乎也没有发现这种问题. 那么第二种情况,可能是内存不足,导

关于打开Eclipse时出现eclipse failed to create the java virtual machine与locking is not possible in the directory问题的解决

今天在机子上使用Eclipse时候打开发现这两个问题,通过查阅资料膜拜大神博客得知解决方法,特此整理下来,方便后来遇到此问题的小伙伴们. 一开始打开Eclipse时候出现问题现象1,问题1解决以后就出现了问题2,. 1.问题1现象(eclipse failed to create the java virtual machine) 2.问题1解决方法 这是创建Java虚拟机初始化失败,找到Eclipse解压路径以及初始化文件 用ultraEdit打开,出现如下图所示情况时,点击“否”或者“取消”

java虚拟机内存不足,“Could not create the Java Virtual Machine”问题解决方案

在运行java程序时,遇到问题"Could not create the Java Virtual Machine."如下截图: 大概原因,就是java堆内存不足以运行JVM,需要增加内存. 网上搜索此问题,大部分都是针对某个程序进行修改JVM内存的解决方法,比如eclipse,等.试问,若是其他程序出现问题了呢? 现在给出一个全局的java虚拟机修改内存的方法.在WIN XP,WIN 7,WIN8都可以. 解决方案:增加一个系统环境变量 变量名:_JAVA_OPTIONS 变量值:-

What is Java virtual machine?

Java Virtual Machine (JVM) is a specification that provides runtime environment in which java  bytecode can be executed. As the name implies, the JVM acts as a “virtual” machine or processor. Java's platform independence consists mostly of its Java V

【cl】解决Fail to create the java Virtual Machine

eclipse打开,提示Fail to create the java Virtual Machine 解决方法: 1.到eclipse安装目录下,找到eclipse.ini 2.按键盘ctrl+F,复制以下字符“launcher.XXMaxPermSize”,去掉引号,查找 3.将随后出现的两个216m改成128m

启动Myeclipse报错“Failed to create the Java Virtual Machine”的解决办法

我安装的是Myeclipse 10.7.1.装上好久没用,今天启动突然报错:Failed to create the Java Virtual Machine. 检查Myeclipse安装好使用时好的啊,近期也没用,可能是近期升级了本地单独安装的jre版本导致的吧(Myeclipse使用自己的jre的). 整理了如下2个解决办法,可以选择一个使用,我选择的是第2个.经测试都ok. 方法一: 找到Myeclpise路径下的myeclipse.ini文件: 编辑将Xmx(JVM Heap最大允许的尺