Java Virtual Machine [JVM]

1. The memory area (runtime data area)

  • Thread private:
    a program counter, Java virtual machine stack, native method stacks
  • Threads share:
    heap, the method area (runtime constant pool), direct memory

    1.1 Program Counter

    Address of the bytecode instructions used for recording the program being executed

    1.2 virtual machine stack

  • Composition:
    Each implementation of a Java method creates a stack frame, each stack frame includes: the local variable table, the operand stack, constant pool references.
    Operand stack: before and after the calculation, for storing data, stack pop
  • Exception:
    When the stack depth of the thread requested exceeds the maximum, StackOverflowError will throw an exception;
    when the stack is dynamically extended if unable to apply enough memory , will throw an OutOfMemoryError.

    1.3 native method stacks

    Local method is generally used in other languages ​​(C, C ++ or assembly language, etc.) written in native method stacks local service method.

    1.4 Heap

    The main area of ​​garbage collection, also called GC heap
  • Composition:
    New Generation (Eden, From survivor, To Survivor ), the old year ()
  • Abnormal:
    OutOfMemoryError abnormal

    1.5 Method Area (permanent generation)

  • Composition:
    used to store class information has been loaded, constants, static variables, the time compiler to compile the code and other data, as well as runtime constant pool.
  • Abnormal:
    OutOfMemoryError abnormal

From the beginning of JDK 1.8, remove the permanent generation method and the yuan to move it to space, which is located in local memory, not virtual machine memory. On behalf of the original data it is permanently assigned to the heap and metaSpace. Meta information storing element space type, a static variable and constant pool, etc. into the stack.

1.6 constant pool

The constant pool mainly used to store two types of constants: literal (the Literal) and symbolic reference amount (Symbolic References).

  • Literal
    equivalent Java language constant level concepts, such as text strings, declared as final constant values and so on;
  • Reference symbol
    conceptual aspects belonging to the principles of compilation, including the following three types of constants:
    (1) the fully qualified name of the classes and interfaces; and
    (2) field names and descriptors;
    (3) the method name and descriptor.

    1.7 Direct Memory

    In JDK 1.4 NIO newly introduced class, it can use Native libraries directly outside the heap memory allocated, then the Java heap DirectByteBuffer this object as referenced memory to operate.

2. Garbage Collection

Mainly for heap (Cenozoic years old) and a method area (permanent behalf)

2.1 What is garbage

  • Reference count (refer to each other, leading to never be recovered)
  • Reachability analysis
    with GC Roots as a starting point, search, reach can not be recovered. As GC Roots: the
    object (1) VM stack local variable table referenced in
    (2) Object native method stack JNI references
    (3) object method area class static attribute references
    (4) Method region constant referenced objects
  • Four kinds of reference:
    (1) strong reference
    (2) cited soft (low memory recovery only)
    (3) weak references (will be recovered during the next garbage collection)
    (4) references virtual (dummy object is set as a reference the sole purpose of the system is able to receive a notification when the object is recovered.)

    2.2 garbage collection algorithm

  • Mark - Clear
  • Mark - finishing
  • Copy (heap of new generation)
  • Generational collection
    Cenozoic: Copy the
    old year: tag or tags to organize cleared

    2.3 garbage collector

    (1)Serial 
    串行、新生代、客户端(默认客户端新生代的收集器)、标记整理
    (2)ParNew
    并行、新生代、服务端(Serial的并行版),只能与CMS配合使用、标记整理
    (3)Parallel Scavenge
    并行、新生代、吞吐量优先(降低了并发数,其他收集器是降低用户线程的停顿时间,提升并发数;减少新生代空间——>垃圾回收频繁——>吞吐量下降,缩短吞吐量牺牲了吞吐量,减少了新生代空间)
    (4)Serial Old
    串行、老年代、客户端
    (5)Parallel Old
    并行、老年代、(服务端后台)
    (6)CMS(Concurrent Mark Sweep并发标记清除)
    并行、老年代、服务端
    低停顿
    过程:初始标记(需要停顿)、并发标记、重新标记(解决并发标记期间发生变化的标记,需要停顿)、并发清除(期间发生引用变化会导致浮动垃圾,只能下一次GC再清理)
    缺点:吞吐量低、无法处理浮动垃圾需要临时使用Serial Old处理、标记清除算法会导致不连续空间的浪费
    (7)G1
    服务端
    引入Region
    过程:初识标记、并发标记、最终标记、筛选回收

    !2.4 内存分配回收策略

  • Minor GC:回收新生代,发生一次Minor GC Eden的对象进入Survivor,年龄增加一岁
  • Full GC:回收老年代和新生代
  • 内存分配策略:
    (1)对象优先分配在Eden
    (2)大对象直接进入老年代(-XX:PretenureSizeThreshold,大于此值的对象直接在老年代分配)
    (3)长期存活的对象进入老年代(-XX:MaxTenuringThreshold 用来定义年龄的阈值)
    (4)动态年龄判断(如果Survivor相同年龄的对象大于Survivor空间的一半,大于等于该年龄的直接进入老年代)
    (5)空间分配担保
    MinorGC之前,老年代最大可用连续空间大于新生代所有对象大小,则安全,否则不安全,出发空间分配担保的检查。
    如果允许担保失败,则判断老年代的连续空间大于之前晋升到老年代对象的平均大小,如果大于则进行尝试MinorGC;
    否则,担保失败,或者老年代空间较小,都会需要先进行一次FullGC

    2.5 GC触发的条件

    MinorGC:Eden满
    FullGC:
  • System.gc()
  • 老年代空间不足
  • 空间分配担保失败(不允许冒险、或者老年代空间不足担保失败)
  • Concurrent Mode Failure(CMS导致的老年代空间不足)

    3. 类加载机制

    3.1 类加载过程

    (1)加载
    获取二进制字节流——>放入方法区——>生成Class对象放入内存作为方法区的入口
  • 通过类的完全限定名称获取定义该类的二进制字节流。
  • 将该字节流表示的静态存储结构转换为方法区的运行时存储结构。
  • 在内存中生成一个代表该类的 Class 对象,作为方法区中该类各种数据的访问入口。
    (2)验证
    (3)准备
    初始化类变量(static修饰的变量),放在方法区的内存。
public static int value1 = 123;  //初始化为0
public static final int value2 = 123;  //初始化为123

(4)解析
将常量池的符号引用替换为直接引用的过程。
(5)初始化
使用用户设置的值初始化,(上面的代码块中)即将123赋值给value1的过程。
初始化阶段是虚拟机执行类构造器 () 方法的过程。
初始化顺序:

  • 静态语句块只能访问到定义在它之前的类变量,定义在它之后的类变量只能赋值,不能访问。
public class Test {
    static {
        i = 0;                // 给变量赋值可以正常编译通过
        System.out.print(i);  // 这句编译器会提示“非法向前引用”
    }
    static int i = 1;
}
  • 父类中定义的静态语句块的执行要优先于子类。
  • 父接口中的变量,只有在子接口中使用时才会初始化。

    3.2 何时出发类初始化

    类初始化也会执行前面的4个步骤
  • 主动引用:
    (1)new、读取设置静态类变量、调用类的静态方法
    (2)反射调用类
    (3)初始化子类触发父类初始化
    (4)JVM执行main方法会触发main所在的类初始化
  • 被动引用(不会触发类初始化)
    (1)子类引用父类静态字段,不会触发子类初始化
System.out.println(SubClass.value);  // value 字段在 SuperClass 中定义

(2)数组定义引用类,不会触发类初始化,只会触发数组类的初始化,数组类继承自Object

SuperClass[] sca = new SuperClass[10];

(3)使用常量不会触发类初始化

System.out.println(ConstClass.HELLOWORLD);

4. 对象

4.1 对象的创建

类加载检查——>内存分配——>初始化零值——>设置对象头——>执行init方法

  • 类加载检查
    根据符号引用检查类是否被加载过,如果没有,加载类。
  • 分配内存
    在堆中为对象分配空间。分配方法:指针碰撞、空闲列表。
    使用哪种方式,根据java堆是否连续决定。堆是否连续与GC算法相关。
    指针碰撞:堆内存规整(Serial、ParNew)时,用过的和没用过的以指针分界,分界值指针将指针移动对象大小的内存即可。
    空闲列表:堆内存不规整(CMS),虚拟机维护一个内存列表,分配内存,更新列表。
    分配内存可能导致线程安全问题,2种方式解决:CAS+失败重试、TLAB(为每个线程在Eden区分配内存)
  • 初始化零值
    对象的实例字段初始化
  • 设置对象头
    设置对象相关信息:
    (1)对象和类的关系
    (2)如何找到类的元数据信息
    (3)对象的哈希值
    (4)对象的GC年龄
  • 执行init方法
    按照程序猿设置的值初始化。

    4.2 对象的内存布局

    对象头、实例数据、对齐填充
  • 对象头:对象的自身运行时数据(哈希码、GC分代年龄、锁状态等)、类型指针
  • 实例数据:各种类型的字段内容
  • 对齐填充:仅仅占位,保证整个对象对齐,8字节的整数倍。

    4.3 对象的访问

    句柄、直接指针
  • 句柄:
    句柄池(堆):到对象实例数据的指针(指向对象实例数据(堆))、到对象类型数据的指针(指向对象类型数据(方法区))
    好处:对象被移动时,只需要改变句柄中的实例数据指针。
  • 直接指针(堆):到对象类型数据的指针(指向对象类型数据(方法区))、对象实例数据(堆)
    好处:少了一次指针定位的时间开销。

Guess you like

Origin www.cnblogs.com/suyeSean/p/11241906.html