Java8中的JVM

Javaer避免不了JVM和GC,谈GC必须先了解JVM,所以就先来看看JVM吧。
本文也仅仅是个人的一点肤浅的理解。

内存结构

首先说说内存结构,也就是Java虚拟机所管理的内存区域:
  1. 程序计数器(Program Counter Register)
  2. Java栈(VM Stack)
  3. 本地方法栈(Native Method Stack)
  4. 方法区(Method Area)
  5. 堆(Heap)。

这5个区域当中,只有程序计数器不会抛出OOM,剩下的4个区域都有可能抛出OOM异常。

这些区域根据对线程可见的情况分为2部分:
1. 线程共享内存区:
 方法区
 堆
2. 线程私有内存区:
 程序计数器
 虚拟机栈
 本地方法栈

线程私有的内存区域会跟随线程一起产生和消亡。
而共享内存区中的对象,所有的线程都可以访问,所以就有可能出现线程安全的问题。

每个区域分别负责什么?

  1. 程序计数器(Program Counter Register)
    如果线程执行的是非native方法,则程序计数器中保存当前需要执行的指令的地址。
    如果线程执行的是native方法,则程序计数器中的值是undefined。
    由于内存当中指令的地址是定长的,所以这个区域是一定不会出现OOM的区域。
    此外之前提到,程序计数器是线程私有内存区,因为每个线程的程序计数器都是保存的自己线程需要执行的指令的地址,互相独立不影响。

  2. Java栈(VM Stack)
    此处的栈,就是数据结构当中的“栈”。它保存了需要被调用的方法的栈帧。
    用递归来举例:

private int getSum(int n) {
        return n == 1 ? 1 : n + getSum(n - 1);
}

当我们调用getSum(10)的时候,先将getSum(10)入栈,运行时发现需要知道getSum(9)的结果才能返回,所以此时getSum(10)不会出栈,而是将getSum(9)入栈,同理入栈getSum(8)、getSum(7)…getSum(1)。在getSum(1)时我们得到明确返回,之后再依次出栈。
虚拟机栈就是保存的getSum(n)的信息,只不过要复杂一些,我们叫它“栈帧”。
在栈帧中包括局部变量表(Local Variables)、操作数栈(Operand Stack)、指向当前方法所属的类的运行时常量池(运行时常量池的概念在方法区部分会谈到)的引用(Reference to runtime constant pool)、方法返回地址(Return Address)和一些额外的附加信息。

理论上讲,当n足够大时,使栈深度大于虚拟机所允许的最大深度,将抛出StackOverFlowError异常。
如果虚拟机栈可以动态扩展,当扩展到无法申请内存到足够的内存,就会抛出OutOfMemoryError异常!

  1. 本地方法栈(Native Method Stack)
    本地方法栈和虚拟机栈作用相似,只不过本地方法栈是保存的native方法的栈帧。
    这个一般web开发设计的比较少,我只在调用dll时调用过native方法。

  2. 方法区(Method Area)
    存放类的各中加载信息,常量、静态变量等。
    在Java8之前,永久区就是方法区的实现,而在Java8中就移除了永久区,用元空间MetaSpace代替。
    现在的元空间是使用本地内存,不会使用虚拟机内存。
    为什么移除永久代?
    a.官方说明:移除永久代是为融合HotSpot JVM与 JRockit VM而做出的努力,因为JRockit没有永久代,不需要配置永久代。
    b.由于永久代内存经常不够用或发生内存泄露,爆出异常java.lang.OutOfMemoryError: PermGen
    这个区域GC基本很少做垃圾回收。

  3. 堆(Heap)。
    这里就是重点了,堆是5个区域中最大的一个区域,用于存放对象的实例。很显然,这里就是GC的主战场。
    为了支持垃圾收集,堆被分为三个部分:
    新生代:划分为Eden区和Survivor区(From Survivor To Survivor),比例为8:1:1。
    老年代:当年轻代中的对象经历多次(由JVM参数MaxTenuringThreshold决定,默认是15次)复制仍然存活,则转移到老年代。
    新生代和老年代所占内存比为1:2。

相关的GC,后面会专门写一篇文章研究。
最近太忙。。。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据