(适合入门)JVM堆内存相关的启动参数:年轻一代、岁和永久代内存分配

假设你要观察JVM进程消耗的堆内存,通过命令工具jmap或可视化工具jvisualvm.exe。JVM这些参数的默认启动值。假设你想知道JVM内存分配策略,最开始手动设置这些参数。通过JDK统计结果,进行对照,就比較easy理解这些内存分配的理论知识。

执行环境是win7 32位操作系统,JDK1.7.0_60版本号。

測试代码和JVM启动參数例如以下:

public class Test
{
    public static void main(String[] args)
    {
        int a = 0;
        while (true)
        {
            a++;
        }
    }
}
-Xms=200M  -Xmx200M -XX:NewSize=100M -Xmn100M -XX:SurvivorRatio=8
-XX:OldSize=60M -XX:PermSize=50M -XX:MaxPermSize=50M

执行上述代码。通过jps命令获取到进程pid。然后通过jmap -heap pid就能够查看内存分配和使用情况。

>jmap -heap 8912
Attaching to process ID 8912, please wait...
Debugger attached successfully.
Client compiler detected.
JVM version is 24.60-b09

using thread-local object allocation.
Mark Sweep Compact GC

Heap Configuration:
   MinHeapFreeRatio = 40
   MaxHeapFreeRatio = 70
   MaxHeapSize      = 209715200 (200.0MB)
   NewSize          = 104857600 (100.0MB)
   MaxNewSize       = 104857600 (100.0MB)
   OldSize          = 62914560 (60.0MB)
   NewRatio         = 3
   SurvivorRatio    = 8
   PermSize         = 52428800 (50.0MB)
   MaxPermSize      = 52428800 (50.0MB)

这里显示的堆配置參数。都能够通过JVM启动參数来设置。

以下来解释下几个重要參数的含义:

-Xms 和 -Xmx (-XX:InitialHeapSize 和 -XX:MaxHeapSize):指定JVM初始占用的堆内存和最大堆内存。JVM也是一个软件。也必需要获取本机的物理内

存,然后JVM会负责管理向操作系统申请到的内存资源。JVM启动的时候会向操作系统申请 -Xms 设置的内存。JVM启动后执行一段时间。假设发现内存空间

不足,会再次向操作系统申请内存。

JVM可以获取到的最大堆内存是-Xmx设置的值。

-XX:NewSize 和 -Xmn(-XX:MaxNewSize):指定JVM启动时分配的新生代内存和新生代最大内存。

-XX:SurvivorRatio:设置新生代中1个Eden区与1个Survivor区的大小比值。

在hotspot虚拟机中。新生代 = 1个Eden + 2个Survivor。假设新生代内存是

10M。SurvivorRatio=8,那么Eden区占8M,2个Survivor区各占1M。

-XX:NewRatio:指定老年代/新生代的堆内存比例。在hotspot虚拟机中,堆内存 = 新生代 + 老年代。

假设-XX:NewRatio=4表示年轻代与年老代所占比值为1:4,年轻代占整个堆内存的1/5。

在设置了-XX:MaxNewSize的情况下,-XX:NewRatio的值会被忽略,老年代的内存=堆内存
- 新生代内存。老年代的最大内存 = 堆内存 - 新生代 最大内存。

-XX:OldSize:设置JVM启动分配的老年代内存大小,类似于新生代内存的初始大小-XX:NewSize。

 -XX:PermSize 和 -XX:MaxPermSize:指定JVM中的永久代(方法区)的大小。

能够看到:永久代不属于堆内存,堆内存仅仅包括新生代和老年代

能够发现:堆内存、新生代内存、老年代内存、永久代内存,都有一个初始内存,另一个最大内存。

以下以老年代的初始内存和最大内存为例,看下内存变化的效果,其它的应该类似。測试代码例如以下:

public class TurnedTest
{
    private static List<String> list = new ArrayList<String>();

    public static void main(String[] args)
    {
        int a = 0;
        while (true)
        {
            a++;

            list.add("demo");
        }

    }
}

显然这个程序存在内存泄露。终于会占满整个堆内存,抛出OOM。为了看清楚这个演变的过程,我们在while循环中加入一个断点,设置breakpoint properties中的"hit count"为100000,以debug模式执行上面的程序。然后使用jmap观察内存占用情况。

   tenured generation:
   capacity = 62914560 (60.0MB)
   used     = 0 (0.0MB)
   free     = 62914560 (60.0MB)
   0.0% used

   tenured generation:
   capacity = 62914560 (60.0MB)
   used     = 16409080 (15.648918151855469MB)
   free     = 46505480 (44.35108184814453MB)
   26.08153025309245% used

   tenured generation:
   capacity = 62914560 (60.0MB)
   used     = 53329496 (50.858970642089844MB)
   free     = 9585064 (9.141029357910156MB)
   84.76495107014973% used

   tenured generation:
   capacity = 104857600 (100.0MB)
   used     = 84217880 (80.3164291381836MB)
   free     = 20639720 (19.683570861816406MB)
   80.3164291381836% used

能够发现老年代内存从最開始的60M,扩大到最大值100M。

版权声明:本文博客原创文章。博客,未经同意,不得转载。

时间: 2024-10-25 14:39:04

(适合入门)JVM堆内存相关的启动参数:年轻一代、岁和永久代内存分配的相关文章

(入门贴)JVM堆内存相关的启动参数:年轻代、老年代和永久代的内存分配

如果想观察JVM进程占用的堆内存,可以通过命令工具jmap或者可视化工具jvisualvm.exe.JVM这些启动参数都拥有默认值,如果想了解JVM的内存分配策略,最好手动设置这些启动参数.再通过JDK提供的工具的统计结果,进行对比,就比较容易理解这些内存分配的理论知识.运行环境是win7 32位操作系统,JDK1.7.0_60版本. 测试代码和JVM启动参数如下: public class Test { public static void main(String[] args) { int

JVM堆内存相关的启动参数:年轻代、老年代和永久代的内存分配

如果想观察JVM进程占用的堆内存,可以通过命令工具jmap或者可视化工具jvisualvm.exe.JVM这些启动参数都拥有默认值,如果想了解JVM的内存分配策略,最好手动设置这些启动参数.再通过JDK提供的工具的统计结果,进行对比,就比较容易理解这些内存分配的理论知识.运行环境是win7 32位操作系统,JDK1.7.0_60版本. 测试代码和JVM启动参数如下: public class Test { public static void main(String[] args) { int

Storm程序永久代内存溢出

在集群中部署Storm应用程序的时候报错,并通过jdk自带的jconsole监控发现,永久代内存瞬间爆炸了 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cacheService' defined in resource loaded from byte array: Invocation of init method failed; nested exception

JVM调优之Tomcat启动参数配置及详解

开发项目中会遇到Tomcat内存溢出(java.lang.OutOfMemoryError: PermGen space)的问题,通过查找资料找到是通过设置Tomcat 启动堆空间大小.年轻代大小.每个线程大小参数进行调优的,具体如下: 一.在Tomcat 启动脚本(catalina.sh/catalina.bat)首行添加如下配置即可解决此问题 JAVA_OPTS="-Xms2048m -Xmx2048m -Xmn1024m -Xss1024K -XX:PermSize=128m -XX:Ma

linux内核可以接受的参数 | Linux kernel启动参数 | 通过grub给内核传递参数

在Linux中,给kernel传递参数以控制其行为总共有三种方法: 1.build kernel之时的各个configuration选项. 2.当kernel启动之时,可以参数在kernel被GRUB或LILO等启动程序调用之时传递给kernel. 3.在kernel运行时,修改/proc或/sys目录下的文件. 这里我简单讲的就是第二种方式了,kernel在grub中配置的启动参数. 首先,kernel有哪些参数呢? 在linux的源代码中,有这样的一个文档Documentation/kern

2 - JVM随笔分类(JVM堆的内存回收)

JVM常用的回收算法是: 标记/清除算法 标记/复制算法 标记/整理算法 其中上诉三种算法都先具备,标记阶段,通过标记阶段,得到当前存活的对象,然后再将非标记的对象进行清除,而对象内存中对象的标记过程,则是使用的  “根搜索算法”,通过遍历整个堆中的GC ROOTS,将所有可到达的对象标记为存活的对象的一种方式,则是 “根搜索算法”,其中根是指的“GC ROOTS”,在JAVA中,充当GC ROOTS的对象分别有:“虚拟机栈中的引用对象”,“方法区中的类静态属性引用的对象”,“方法区中的常量引用

JDK8内存模型—消失的永久代

一.JVM 内存模型 根据 JVM 规范,JVM 内存共分为虚拟机栈.堆.方法区.程序计数器.本地方法栈五个部分. 1.虚拟机栈:每个线程有一个私有的栈,随着线程的创建而创建.栈里面存着的是一种叫“栈帧”的东西,每个方法会创建一个栈帧,栈帧中存放了局部变量表(基本数据类型和对象引用).操作数栈.方法出口等信息.栈的大小可以固定也可以动态扩展.当栈调用深度大于JVM所允许的范围,会抛出StackOverflowError的错误,不过这个深度范围不是一个恒定的值,我们通过下面这段程序可以测试一下这个

Java8内存模型—永久代(PermGen)和元空间(Metaspace)(转)

一.JVM 内存模型 根据 JVM 规范,JVM 内存共分为虚拟机栈.堆.方法区.程序计数器.本地方法栈五个部分. 1.虚拟机栈:每个线程有一个私有的栈,随着线程的创建而创建.栈里面存着的是一种叫“栈帧”的东西,每个方法会创建一个栈帧,栈帧中存放了局部变量表(基本数据类型和对象引用).操作数栈.返回地址等信息.栈的大小可以固定(编译时确定)也可以动态扩展.当栈调用深度大于JVM所允许的范围,会抛出StackOverflowError的错误,不过这个深度范围不是一个恒定的值,我们通过下面这段程序可

Java8内存模型—永久代(PermGen)和元空间(Metaspace)

一.JVM 内存模型 根据 JVM 规范,JVM 内存共分为虚拟机栈.堆.方法区.程序计数器.本地方法栈五个部分. 1.虚拟机栈:每个线程有一个私有的栈,随着线程的创建而创建.栈里面存着的是一种叫"栈帧"的东西,每个方法会创 建一个栈帧,栈帧中存放了局部变量表(基本数据类型和对象引用).操作数栈.方法出口等信息.栈的大小可以固定也可以动态扩展.当栈调用深度大于JVM所 允许的范围,会抛出StackOverflowError的错误,不过这个深度范围不是一个恒定的值,我们通过下面这段程序可