Java JVM 7:内存结构

来源:互联网 发布:最好的网络推广公司 编辑:程序博客网 时间:2024/05/22 23:15

JVM 一般可以分为 PC 寄存器,JVM 方法栈,本地方法栈,JVM 方法区 以及 JVM 堆,如下图:

这里写图片描述

PC 寄存器:可以看做是当前线程所执行的字节码的行号指示器。它属于每个线程所私有的。

JVM 方法栈:由一条条的栈帧组成,每个栈帧又包括了局部变量区,操作数区,等。每个方法在执行的时候就会创建一个栈帧(所以说递归会产生大量的栈帧,假如此时又死循环了,那么这里栈帧过多,就会造成 stackoverflow 栈溢出异常。)它也是线程所私有的。

本地方法栈:主要用于支持 java 语言和其他语言(如C语言)的一个交互。

JVM 方法区:存储 JVM 加载了的 类的信息,常量,静态变量等。简单来说就相当于平常所说的永久代。(实际上肯定有区别,但是对于新手来说可以暂且认为差不多,相等)。这部分区域不是线程所私有,而是各个线程所共享的。

JVM 堆:这里主要用于存储对象和数组等实例。是 Java 最重要的一块存储区域,平常所说的堆内存,新生代(eden,survivor区域),老年代就是在这个区域中。因此,这里也是垃圾收集的主要发生的场所。

上面几个都是 JVM 的规范,但是 JVM 方法区在 JDK7 和 JDK8 的实现有不同,在 JDK7 中是永久代,在 JDK8 中使用 MetaSpace。

对于 MetaSpace,可以参考:Java 8: 从永久代(PermGen)到元空间(Metaspace),简单来说,会有一些好处,比如说这部分的内存大小只受到本地内存的限制,所以就不会出现之前的永久代溢出的问题。

JVM 堆内存划分

对于JVM 的内存区域,还有一个经常谈论的地方就是 JVM堆,主要分为了新生代和老年代。其中:

新生代又分为了 1 个 Eden 区域和 2 个 Survivor 区域,比例是 8:1:1。这样的一个划分主要是因为新生代采用的垃圾回收算法为复制算法而导致的。

对于老年代,和新生代的比例默认为 2:1。

对于一些调整的参数这里罗列总结一下:

-XX: Persize:设置非堆内存初始值,默认为1/64。(JDK7的JVM方法区内存)

-XX:MaxPersize:设置非堆内存最大值,默认为1/4。(JDK7的JVM方法区内存)

-Xss:设置每个线程占用堆内存大小,现在默认为1M,以前为256K。设置线程越小,堆内存大小不变,可以创造的线程数越多(当然有一个限度)。但是这个值也需要经过严格的测试再设置。

-Xms:JVM堆初始分配内存。默认为物理内存的1/64,当默认堆内存的空余空间小于40%的时候,这个堆内存就会自动增长到-Xmx指定的最大堆分配内存。

-Xmx :JVM的最大堆分配内存。默认为物理内存的1/4,当空余内存大于70%的时候,该堆内存又会自动减少到-Xms指定的内存。

-Xmn:指定新生代的内存大小。当堆大小不变的情况下,新生代越大,老生代越小,默认新生代和老年代的比例为1:2,而且这个比例会严重影响系统性能,sun推荐为新生代占整个堆内存3/8

-XX:SurvivorRatio:新生代中,又分为eden区域和两个Survivor区域。默认比例为8:1:1,也就是说,可以用的内存为90%。该参数用来设置eden和Survivor的比值,默认为8:1。

-XX:NewRatio:年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)

0 0
原创粉丝点击