JVMS7笔记

Structure of JVM


DataTypes:

  • primitive types

    • Integral Types : int, long, short, char。
    • Boolean Type : 计算的时候使用int。
    • Floating-Point Types : float, double。
    • the returnAddress Type : 开发不能直接使用。
  • reference types

    • 足够长来存储指针,长度一般与机器位数相同。

Runtime Data Areas:

  • The pc Register

    正常指向指令的地址。

    • 执行native方法的时候,pc是不存在值的。
  • Java Virtual Machine Stacks

    每个线程都有自己的stack,stack存储了frames。

    • frame

      A frame is used to store data and partial results, as well as to perform dynamic linking, return values for methods, and dispatch exceptions.

      A new frame is created each time a method is invoked. A frame is destroyed when its method invocation completes, whether that completion is normal or abrupt (it throws an uncaught exception). Frames are allocated from the Java virtual machine stack (§2.5.2) of the thread creating the frame. Each frame has its own array of local variables (§2.6.1), its own operand stack (§2.6.2), and a reference to the runtime constant pool (§2.5.5) of the class of the current method.

      • Local Variables

        一个local variable 占用一个word size;long,double占用两个word size,所以是两个local variable。 0 local variable 为被调用的method所在的object的reference(即this),方法的参数从1 local variable 开始连续 存储。

        JVM 设计的word size 不同于 word(8 bits) in computer science:
        
        The basic unit of size for data values in the Java virtual machine is the word--a fixed size chosen by the designer of each Java virtual machine implementation. The word size must be large enough to hold a value of type byte, short, int, char, float, returnAddress, or reference. Two words must be large enough to hold a value of type long or double. An implementation designer must therefore choose a word size that is at least 32 bits, but otherwise can pick whatever word size will yield the most efficient implementation. The word size is often chosen to be the size of a native pointer on the host platform.
        
      • Operand Stacks

        Each frame (§2.6) contains a last-in-first-out (LIFO) stack known as its operand stack.
        
      • Dynamic Linking

        The class file code for a method refers to methods to be invoked and variables to be accessed via symbolic references.
        
      • Special Methods

        每一个construction都是<init>方法;每一个默认的Void 且没有参数的contruction是<clinit>方法。
        they are never invoked directly from any Java virtual machine instruction, but are invoked only indirectly as part of the class initialization process.
        signature polymorphic(MethodHandler)这个也是JDK7加入的,为了实现JSR292,为在JVM上实现动态语言提供更多的支持。MethodHandle是JSR292的重要组成部分之一。invokevirtual 指令会对siglenature polymorphic methodMethodHandler以及子类)多特殊处理。
        
      • Exception

        同步异常(synchronous exception)抛出的方式:
        1. athrow 指令的调用
        2. JVM相关的Error,类loading,liking阶段相关的Exception,OutOfMemory,StackOverflow,RuntimeException的继承类等。
        异步异常(asynchronous exception)抛出的方式:
        1. Thread或者ThreadGroup的stop方法被触发。
        2. JVM内部的错误
            JVM允许异步的异常抛出存在一定的延迟,在最适合的时候记性处理--在这段延迟中,可以让JVM重排指令来优化代码和计算。(比较简单的实现方式是:在每条[control transfer instruction]执行的时候才去poll异步的异常。正是因为有这个保证,所以control transfer instruction之间的指令能够被JVM优化)
        

        在class文件中,excpetion handlers都存在table里面。

  • Heap

    Heap的管理是通过automacic storage management system,JVMS的实现可以实现自己heap管理机制。

  • Method Area

    It stores per-class structures such as the runtime constant pool, field and method data, and the code for methods and constructors, including the special methods (§2.9) used in class and instance initialization and interface initialization

    • 一般JVMS简单的实现是不会选择去处理Method Area的,但是这个版本的JVMS没有强制要求这么做。

    • Runtime Constant Pool

      A runtime constant pool is a per-class or per-interface runtime representation of the constant_pool table in a class file4.4). It contains several kinds of constants, ranging from numeric literals known at compile-time to method and field references that must be resolved at runtime. The runtime constant pool serves a function similar to that of a symbol table for a conventional programming language, although it contains a wider range of data than a typical symbol table.
      

Instruction Summary:

字节码指令流一般是按照字节排列的,只有lookupswitch & tableswitch 比较特别。

  • instructions with type info:

    指令集里面有部分是可以之间看出类型,比如iadd表示可以计算int类型的数据,fadd表示计算float类型的的数据等。但是要每个指令都支持所有的类型,是不现实的,因为一个byte只有8位。所以最后char,boolean,short等的add指令都会被转换成int的计算(使用iadd)。

  • instructions regardless of type info:

    指令集里面的类似push,pop,swap等是不带type信息的,只关心使用到的category of computational types。

    • Category 1:

      boolean, byte, char, short, int 的计算类型是 int; float计算类型位float;reference为reference;returnAddress为returnAddress;

    • Category 2:

      long的计算类型为long, double计算类型为double,

  • 指令概览

    • 支持的类型widening指令( i2l, i2f, i2d, l2f, l2d, and f2d):

      • int to long, float, or double
      • long to float or double
      • float to double
    • 支持的narrowing指令(i2b, i2c, i2s, l2i, f2i, f2l, d2i, d2l, and d2f):

      • int to byte, short, or char
      • long to int
      • float to int or long
      • double to int, long, or float

      类型转换过程中,会存在一定的信息丢失情况,具体需要具体翻看了解。

    • 支持的 control transfer instruction 分为以下几类:

      • conditional branch:

        ifeq, ifne, iflt, ifle, ifgt, ifge, ifnull, ifnonnull, if_icmpeq, if_icmpne, if_icmplt, if_icmple, if_icmpgt if_icmpge, if_acmpeq, if_acmpne

      • compound conditional brach:

        tableswitch, lookupswitch

      • unconditional brach:

        goto, goto_w, jsr, jsr_w, ret

    • 5种方法调用指令:

      • invokevirtual: 调用类实例的方法
      • invokeinterface: ???
      • invokespecial: init, private, super class的方法
      • invokestatic: 调用类的方法
      • invokedynamic: 关联到MethodHandle,看了相关的资料,暂时还没有领会其用途(???)
    • 同步, 分为两类:

      • method synchronization
      • block synchronization

        moniterenter,moniterexit 这两个指令配合完成同步。


Compiling for JVM

tableswitch是switch 连续的int 和 lookupswitch是switch离散的int。排序过的switch key 效率更高;tableswitch效率比lookupswitch高。

try-catch statements:

As a subtle point, note that the range of a catch clause is inclusive on the "from" end and exclusive on the "to" end.

A Java virtual machine implementation verifies that each class file satisfies the necessary constraints at linking time

String.intern() 会找到runtime constant pool中相同字符串的引用地址

skip Class file format & Verification of Class Files


Loading, Linking, and Initializing

VM Start-up

调用bootstrap classloader 加载 初始化类,然后加载main方法;一般jvm的实现都有 命令行参数 或者 提供 初始化参数的方式。

Creation and Loading

C代表一个interface or class;

N代表internal name of C in JVM implementation;

D触发了C的创建:D的runtime contant pool有C的引用 或者 D通过反射创建C

A class loader L may create C by defining it directly or by delegating to another class loader. If L creates C directly, we say that L defines C or, equivalently, that L is the defining loader of C.

When one class loader delegates to another class loader, the loader that initiates the loading is not necessarily the same loader that completes the loading and defines the class. If L creates C, either by defining it directly or by delegation, we say that L initiates loading of C or, equivalently, that L is an initiating loader of C.

The Java virtual machine uses one of three procedures to create class or interface C denoted by N:

  • If N denotes a nonarray class or an interface, one of the two following methods is used to load and thereby create C:

    • If D was defined by the bootstrap class loader, then the bootstrap class loader initiates loading of C.

    • If D was defined by a user-defined class loader, then that same user-defined class loader initiates loading of C.

  • Otherwise N denotes anarray class.An array class is created directly by the Java virtual machine, not by a class loader. However, the defining class loader of D is used in the process of creating array class C.

在loading的阶段出现异常,抛出LinkageError的继承类。

< $$$ N, L_d $$$ > : N denotes the name of the class or interface and $$$ L_d $$$ denotes the defining loader of the class or interface.

$$$ N^{L_i} $$$ : N denotes the name of the class or interface and $$$ L_i $$$ denotes an initiating loader of the class or interface.


Linking:

如果JVM在Verification or Resolution class C的时候抛出了ClassNotFoundException的时候,会被包装成NoClassDefFoundError.(Loading of superclass 是 Rsolution逻辑的一部分)

  • Verification
  • Prepare
  • Resolusion: 这个可能在真正使用的时候(懒加载,invokedynamic指令)才会使用到;也有情况是直接使用。

Initializing:

ClassLoader.loadClass() 与 Class.forName()
ClassLoader.loadClass(String name, boolean resolve),其中resolve默认为false,即只执行类装载的第一个阶段。

Class.forName(String name, boolean initialize, ClassLoader loader), 其中initialize默认为true,即执行到类装载的第三个阶段。