JVM之参数分配(全面讲解)

一、堆参数设置

-XX:+PrintGC 使用这个参数,虚拟机启动后,只要遇到GC就会打印日志

-XX:+UseSerialGC 配置串行回收器

-XX:+PrintGCDetails 可以查看详细信息,包括各个区的情况

-Xms:设置Java程序启动时初始化堆大小

-Xmx:设置Java程序能获得最大的堆大小

-Xmx20m -Xms5m -XX:+PrintCommandLineFlags:可以将隐式或者显示传给虚拟机的参数输出

在实际工作中,我们可以直接将初始的堆大小与最大堆大小设置相等,这样的好处是可以减少程序运行时的垃圾回收次数,从而提高性能。

配置运行时参数:-XX:+PrintGC -Xms5m -Xmx20m -XX:+UseSerialGC -XX:+PrintGCDetails -XX:+PrintCommandLineFlags

运行一下Demo:

package com.ietree.basicskill.jvm;

public class Demo01 {
  public static void main(String[] args) {

    // -XX:+PrintGC -Xms5m -Xmx20m -XX:+UseSerialGC -XX:+PrintGCDetails -XX:+PrintCommandLineFlags

    //查看GC信息
    System.out.println("max memory:" + Runtime.getRuntime().maxMemory());
    System.out.println("free memory:" + Runtime.getRuntime().freeMemory());
    System.out.println("total memory:" + Runtime.getRuntime().totalMemory());

    byte[] b1 = new byte[1*1024*1024];
    System.out.println("分配了1M");
    System.out.println("max memory:" + Runtime.getRuntime().maxMemory());
    System.out.println("free memory:" + Runtime.getRuntime().freeMemory());
    System.out.println("total memory:" + Runtime.getRuntime().totalMemory());

    byte[] b2 = new byte[4*1024*1024];
    System.out.println("分配了4M");
    System.out.println("max memory:" + Runtime.getRuntime().maxMemory());
    System.out.println("free memory:" + Runtime.getRuntime().freeMemory());
    System.out.println("total memory:" + Runtime.getRuntime().totalMemory());

  }
}

程序输出:

-XX:InitialHeapSize=5242880 -XX:MaxHeapSize=20971520 -XX:+PrintCommandLineFlags -XX:+PrintGC -XX:+PrintGCDetails -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseSerialGC
max memory:20316160
free memory:5286032
total memory:6094848
[GC (Allocation Failure) [DefNew: 789K->191K(1856K), 0.0026441 secs] 789K->530K(5952K), 0.0027627 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
分配了1M
max memory:20316160
free memory:4469352
total memory:6094848
[GC (Allocation Failure) [DefNew: 1249K->0K(1856K), 0.0022285 secs][Tenured: 1554K->1554K(4096K), 0.0031394 secs] 1587K->1554K(5952K), [Metaspace: 2597K->2597K(1056768K)], 0.0054980 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
分配了4M
max memory:20316160
free memory:4538184
total memory:10358784
Heap
 def new generation  total 1920K, used 68K [0x00000000fec00000, 0x00000000fee10000, 0x00000000ff2a0000)
 eden space 1728K,  3% used [0x00000000fec00000, 0x00000000fec113e0, 0x00000000fedb0000)
 from space 192K,  0% used [0x00000000fedb0000, 0x00000000fedb0000, 0x00000000fede0000)
 to  space 192K,  0% used [0x00000000fede0000, 0x00000000fede0000, 0x00000000fee10000)
 tenured generation  total 8196K, used 5650K [0x00000000ff2a0000, 0x00000000ffaa1000, 0x0000000100000000)
  the space 8196K, 68% used [0x00000000ff2a0000, 0x00000000ff824888, 0x00000000ff824a00, 0x00000000ffaa1000)
 Metaspace    used 2603K, capacity 4486K, committed 4864K, reserved 1056768K
 class space  used 288K, capacity 386K, committed 512K, reserved 1048576K

在此程序输出的结果中,可以看到堆的详细信息,比如可以看到它的新生代信息、老年代信息、永久区信息等。

二、新生代参数配置

-Xmn:可以设置新生代的大小,设置一个比较大的新生代会减少老年代的大小,这个参数对系统性能以及GC行为有很大的影响,新生代大小一般会设置整个堆空间的1/3到1/4左右。

-XX:SurvivorRatio:用来设置新生代中eden空间和from/to空间的比例。含义:-XX:SurvivorRatio=eden/from=eden/to。
不同的堆分布情况,对系统执行会产生一定的影响,在实际工作中,应该根据系统的特点做出合理的配置,基本策略:尽可能将对象预留在新生代,减少老年代的GC次数。

除了可以设置新生代的绝对大小(-Xmn),还可以使用(-XX:NewRatio)设置新生代和老年代的比例:-XX:NewRatio=老年代/新生代。

配置运行时参数:

-Xms20m -Xmx20m -Xmn1m -XX:SurvivorRatio=2 -XX:+PrintGCDetails
-XX:+UseSerialGC

运行Demo:

package com.ietree.basicskill.jvm;

public class Demo2 {
  public static void main(String[] args) {

    // 第一次配置(eden 2 = from 1 + to 1)
    // -Xms20m -Xmx20m -Xmn1m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC

    // 第二次配置
    // -Xms20m -Xmx20m -Xmn7m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC

    // 第三次配置
    // -XX:NewRatio=老年代/新生代
    // -Xms20m -Xmx20m -XX:NewRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC

    byte[] b = null;
    // 连续向系统申请10MB空间
    for (int i = 0; i < 10; i++) {
      b = new byte[1 * 1024 * 1024];
    }
  }
}

程序运行结果:

[GC (Allocation Failure) [DefNew: 508K->256K(768K), 0.0012770 secs] 508K->435K(20224K), 0.0013333 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
 def new generation  total 768K, used 498K [0x00000000fec00000, 0x00000000fed00000, 0x00000000fed00000)
 eden space 512K, 47% used [0x00000000fec00000, 0x00000000fec3c988, 0x00000000fec80000)
 from space 256K, 100% used [0x00000000fecc0000, 0x00000000fed00000, 0x00000000fed00000)
 to  space 256K,  0% used [0x00000000fec80000, 0x00000000fec80000, 0x00000000fecc0000)
 tenured generation  total 19456K, used 10419K [0x00000000fed00000, 0x0000000100000000, 0x0000000100000000)
  the space 19456K, 53% used [0x00000000fed00000, 0x00000000ff72cf20, 0x00000000ff72d000, 0x0000000100000000)
 Metaspace    used 2601K, capacity 4486K, committed 4864K, reserved 1056768K
 class space  used 288K, capacity 386K, committed 512K, reserved 1048576K

可以看到,在新生代种,eden区域内存是from和to区域内存的2倍。即-XX:SurvivorRatio=2参数起了作用。

配置运行参数:-Xms20m -Xmx20m -XX:NewRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC

运行以上Demo可以得到一下输出:

[GC (Allocation Failure) [DefNew: 4979K->529K(6144K), 0.0028804 secs] 4979K->1553K(19840K), 0.0029572 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 5756K->0K(6144K), 0.0021035 secs] 6780K->2576K(19840K), 0.0021487 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
 def new generation  total 6144K, used 1134K [0x00000000fec00000, 0x00000000ff2a0000, 0x00000000ff2a0000)
 eden space 5504K, 20% used [0x00000000fec00000, 0x00000000fed1b9d8, 0x00000000ff160000)
 from space 640K,  0% used [0x00000000ff160000, 0x00000000ff160000, 0x00000000ff200000)
 to  space 640K,  0% used [0x00000000ff200000, 0x00000000ff200000, 0x00000000ff2a0000)
 tenured generation  total 13696K, used 2576K [0x00000000ff2a0000, 0x0000000100000000, 0x0000000100000000)
  the space 13696K, 18% used [0x00000000ff2a0000, 0x00000000ff524140, 0x00000000ff524200, 0x0000000100000000)
 Metaspace    used 2601K, capacity 4486K, committed 4864K, reserved 1056768K
 class space  used 288K, capacity 386K, committed 512K, reserved 1048576K

发现tenured generation老年代的内存是new generation 新生代内存的2倍。

三、堆溢出参数配置

在Java程序的运行过程中,如果对空间不足,则会抛出内存溢出的错误(Out Of Memory)OOM,一旦这类问题发生在生产环境,则可能引起严重的业务中断,Java虚拟机提供了-XX:+HeapDumpOnOutOfMemoryError,
使用该参数可以在内存溢出时导出整个堆信息,与之配合使用的还有参数-XX:HeapDumpPath,可以设置导出堆的存放路径。
内存分析工具:Memory Analyzer

配置运行时参数-Xms1m -Xmx1m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/Demo3.dump

运行Demo:

package com.ietree.basicskill.jvm;

import java.util.Vector;

public class Demo3 {
  public static void main(String[] args) {
    // -Xms1m -Xmx1m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/Demo3.dump
    // 堆内存溢出
    Vector v = new Vector();
    for (int i = 0; i < 5; i++) {
      v.add(new Byte[1 * 1024 * 1024]);
    }
  }
}

程序输出的结果:

java.lang.OutOfMemoryError: Java heap space
Dumping heap to d:/Demo3.dump ...
Heap dump file created [1219372 bytes in 0.009 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
  at com.ietree.basicskill.jvm.Demo3.main(Demo3.java:11)

在d:/Demo3.dump可以找到对应的文件,使用内存分析工具(Memory analyzer)打开:

如图:

四、栈参数配置

Java虚拟机提供了参数-Xss来指定线程的最大栈空间,整个参数也直接决定了函数可调用的最大深度。

配置运行时参数:-Xss1m

运行Demo:

package com.ietree.basicskill.jvm;

public class Demo4 {
  // -Xss1m
  // -Xss5m

  // 栈调用深度
  private static int count;

  public static void recursion() {
    count++;
    recursion();
  }

  public static void main(String[] args) {
    try {
      recursion();
    } catch (Throwable t) {
      System.out.println("调用最大深入:" + count);
      t.printStackTrace();
    }
  }
}

程序输出:

调用最大深入:20557
java.lang.StackOverflowError
  at com.ietree.basicskill.jvm.Demo4.recursion(Demo4.java:12)
  at com.ietree.basicskill.jvm.Demo4.recursion(Demo4.java:12)
  at com.ietree.basicskill.jvm.Demo4.recursion(Demo4.java:12)
  at com.ietree.basicskill.jvm.Demo4.recursion(Demo4.java:12)
  at com.ietree.basicskill.jvm.Demo4.recursion(Demo4.java:12)
  at com.ietree.basicskill.jvm.Demo4.recursion(Demo4.java:12)
  at com.ietree.basicskill.jvm.Demo4.recursion(Demo4.java:12)
  at com.ietree.basicskill.jvm.Demo4.recursion(Demo4.java:12)
  ......

五、方法区参数配置

和Java堆一样,方法区是一块所有线程共享的内存区域,它用于保存系统的类信息,方法区(永久区)可以保存多少信息可以对其进行配置,在默认情况下,-XX:MaxPermSize为64M,
如果系统运行时生产大量的类,就需要设置一个相对合适的方法区,以免出现永久区内存溢出的问题。

-XX:PermSize=64M -XX:MaxPermSize=64M

六、直接内存参数配置

直接内存也是Java程序中非常重要的组成部分,特别是广泛用在NIO中,直接内存跳过了Java堆,使用Java程序可以直接访问原生堆空间,因此在一定程度上加快了内存空间的访问速度。

但是说直接内存一定就可以提高内存访问速度也不见得,具体情况具体分析。

相关配置参数:-XX:MaxDirectMemorySize,如果不设置,默认值为最大堆空间,即-Xmx。直接内存使用达到上限时,就会触发垃圾回收,如果不能有效的释放空间,就会引起系统的OOM。

七、对象进入老年代的参数配置

一般而言,对象首次创建会被放置在新生代的eden区,如果没有GC介入,则对象不会离开eden区,那么eden区的对象如何进入老年代呢?

通常情况下,只要对象的年龄达到一定的大小,就会自动离开年轻代进入老年代,对象年龄是由对象经历数次GC决定的,在新生代每次GC之后如果对象没有被回收,则年龄加1。

虚拟机提供了一个参数来控制新生代对象的最大年龄,当超过这个年龄范围就会晋升老年代。

-XX:MaxTenuringThreshold,默认情况下为15

配置运行时参数:-Xmx64M -Xms64M -XX:+PrintGCDetails

运行Demo:

package com.ietree.basicskill.jvm;

public class Demo5 {
  public static void main(String[] args) {
    // 初始的对象在eden区
    // 参数:-Xmx64M -Xms64M -XX:+PrintGCDetails
    for (int i = 0; i < 5; i++) {
      byte[] b = new byte[1024 * 1024];
    }

  }
}

程序输出:

Heap
 PSYoungGen   total 18944K, used 6759K [0x00000000feb00000, 0x0000000100000000, 0x0000000100000000)
 eden space 16384K, 41% used [0x00000000feb00000,0x00000000ff199db8,0x00000000ffb00000)
 from space 2560K, 0% used [0x00000000ffd80000,0x00000000ffd80000,0x0000000100000000)
 to  space 2560K, 0% used [0x00000000ffb00000,0x00000000ffb00000,0x00000000ffd80000)
 ParOldGen    total 44032K, used 0K [0x00000000fc000000, 0x00000000feb00000, 0x00000000feb00000)
 object space 44032K, 0% used [0x00000000fc000000,0x00000000fc000000,0x00000000feb00000)
 Metaspace    used 2601K, capacity 4486K, committed 4864K, reserved 1056768K
 class space  used 288K, capacity 386K, committed 512K, reserved 1048576K

结论:对象首次创建会被放置在新生代的eden区,因此输出结果中from和to区都为0%。

根据设置MaxTenuringThreshold参数,可以指定新生代对象经过多少次回收后进入老年代。另外,大对象新生代eden区无法装入时,也会直接进入老年代。

JVM里有个参数可以设置对象的大小超过在指定的大小之后,直接晋升老年代。
-XX:PretenureSizeThreshold=15

参数:-Xmx1024M -Xms1024M -XX:+UseSerialGC -XX:MaxTenuringThreshold=15 -XX:+PrintGCDetails

使用PretenureSizeThreshold可以进行指定进入老年代的对象大小,但是要注意TLAB区域优先分配空间。虚拟机对于体积不大的对象 会优先把数据分配到TLAB区域中,因此就失去了在老年代分配的机会.

参数:-Xmx30M -Xms30M -XX:+UseSerialGC -XX:+PrintGCDetails -XX:PretenureSizeThreshold=1000 -XX:-UseTLAB

八、TLAB参数配置

TLAB全称是Thread Local Allocation Buffer即线程本地分配缓存,从名字上看是一个线程专用的内存分配区域,是为了加速对象分配对象而生的。

每一个线程都会产生一个TLAB,该线程独享的工作区域,Java虚拟机使用这种TLAB区来避免多线程冲突问题,提高了对象分配的效率。

TLAB空间一般不会太大,当大对象无法在TLAB分配时,则会直接分配到堆上。

-XX:+UseTLAB使用TLAB

-XX:+TLABSize设置TLAB大小

-XX:TLABRefillWasteFraction设置维护进入TLAB空间的单个对象大小,它是一个比例值,默认为64,即如果对象大于整个空间的1/64,则在堆创建对象。

-XX:+PrintTLAB查看TLAB信息

-XX:ResizeTLAB自调整TLABRefillWasteFraction阈值。

参数:-XX:+UseTLAB -XX:+PrintTLAB -XX:+PrintGC -XX:TLABSize=102400 -XX:-ResizeTLAB -XX:TLABRefillWasteFraction=100 -XX:-DoEscapeAnalysis -server

以上这篇JVM之参数分配(全面讲解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • JVM 参数配置详细介绍

     JVM参数配置 设置堆大小 -Xms 初始堆大小 -Xmx 最大堆大小 -Xmn 设置年轻代大小 设置每个线程堆栈大小 -Xss 设置每个线程的堆栈大小 设置年轻代大小 -XX:NewSize= -XX:MaxNewSize=设置年轻代大小 -XX:NewRatio=设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代) -XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值 设置持久代大小 -XX:MaxPermSize=设置持久代大

  • 在java代码中获取JVM参数的方法

    实例如下: MemoryMXBean memorymbean = ManagementFactory.getMemoryMXBean(); MemoryUsage usage = memorymbean.getHeapMemoryUsage(); System.out.println("INIT HEAP: " + usage.getInit()); System.out.println("MAX HEAP: " + usage.getMax()); System.

  • JVM之参数分配(全面讲解)

    一.堆参数设置 -XX:+PrintGC 使用这个参数,虚拟机启动后,只要遇到GC就会打印日志 -XX:+UseSerialGC 配置串行回收器 -XX:+PrintGCDetails 可以查看详细信息,包括各个区的情况 -Xms:设置Java程序启动时初始化堆大小 -Xmx:设置Java程序能获得最大的堆大小 -Xmx20m -Xms5m -XX:+PrintCommandLineFlags:可以将隐式或者显示传给虚拟机的参数输出 在实际工作中,我们可以直接将初始的堆大小与最大堆大小设置相等,

  • IntelliJ IDEA设置JVM运行参数的操作方法

    打开 IDEA 安装目录,看到有一个 bin 目录,其中有两个 vmoptions 文件,需针对不同的JDK进行配置: 32 位:idea.exe.vmoptions 64 位:idea64.exe.vmoptions -Xms512m -Xmx1024m -XX:MaxPermSize=512m -XX:ReservedCodeCacheSize=225m -XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=50 -ea -Dsun.io.u

  • C语言编程C++动态内存分配示例讲解

    目录 动态内存管理 为什么存在动态内存分配 动态内存函数的介绍 malloc申请空间和free释放空间 有借有还 free释放内存 calloc申请内存 realloc调整动态内存的大小 realloc使用的注意事项 当然realloc也可以直接开辟空间 常见的动态内存错误 1.对NULL指针的解引用操作 2.对动态开辟空间的越界访问 3.对非动态开辟内存使用free释放 4.使用free释放一块动态内存开辟的一部分 5.对同一块动态内存多次释放 6.动态开辟内存忘记释放(内存泄漏) 几个面试题

  • JVM内存参数配置详解

    首先我们知道:JVM发生内存错误的类型 1.堆内存泄漏:OutOfMemory:Java heap space 此种内存泄漏,增加内存,只能暂时解决问题,并不能根治问题.必须要优化代码,一定是代码的问题:排查堆中的大量对象,就会发现,这些对象都被引用,对象不能及时被回收,导致超出了堆的设定最大内存. 2.老年代内存泄漏:OutOfMemoryError:PermGen space 类名.访问修饰符.字段描述.方法描述等,所占空间大于永久代最大值,就会出现,一般都是初始化内存的时候,空间太小,解决

  • Eclipse IDE中如何设置JVM启动参数

    目录 如何设置JVM启动参数 下面是一些设置的步骤 在Eclipse上手动设置jvm参数 典型设置 如何设置JVM启动参数 关于<深入理解Java虚拟机>里面测试OutOfMemoryError异常的部分,需要对虚拟机的启动参数进行设置 下面是一些设置的步骤 1. 右键选择项目,在弹出的菜单进行选择 2. 在弹出的Debug Configurations面板,左侧的type filter text下面选择Java Application,找到自己的项目,例如我的项目HeapOOM. 3. 在D

  • 基于vue.js路由参数的实例讲解——简单易懂

    vue中,我们构建单页面应用时候,一定必不可少用到vue-router vue-router 就是我们的路由,这个由vue官方提供的插件 首先在我们项目中安装vue-router路由依赖 第一种,我们提供命令行来安装 npm install vue-router --save 第二种,我们直接去官方github下载 https://github.com/vuejs/vue-router 路由参数设置 1,实例化一个路由,然后路由映射表中的地址带参数,这个参数就是路由的参数 接着给映射表中的路由设

  • IDEA设置JVM运行参数的方法步骤

    前言 有时候我们需要在程序运行的时候对程序设置环境变量,恰巧我也遇到了这个问题,所以在此记录一下IDEA是如何设置环境变量的. 作用   -Dproperty=Value 该参数通常用于设置系统级全局变量值,如配置文件路径,保证该属性在程序中任何地方都可访问.当然,也可以通过在程序中使用System.setProperty进行设置. 注意: 1.如果-Dproperty=value的value中包含空格,可以将value使用引号引起来.例如:-Dmyname="hello world"

  • PHP引擎php.ini参数优化深入讲解

    PHP引擎php.ini参数优化 无论是apache还是nginx,php.ini都是适合的.而php-fpm.conf适合nginx+fcgi的配置 首先选择产品环境的php.ini(php.ini-production) /home/oldboy/tools/php-5.3.27/php.ini-development /home/oldboy/tools/php-5.3.27/php.ini-production 1.打开php的安全模式 php的安全模式是个非常重要的php内嵌的安全机制

  • idea设置JVM运行参数的几种方式

    目录 方式一 方式二 方式三 对JVM运行参数进行修改是JVM性能调优的重要手段,下面介绍在应用程序开发过程中JVM参数设置的几种方式. 方式一 java程序运行时指定 -Dproperty=value 该参数通常用于设置系统级全局变量值,如配置文件路径,保证该属性在程序中任何地方都可访问.当然,也可以通过在程序中使用System.setProperty进行设置. 注意: 1.如果-Dproperty=value的value中包含空格,可以将value使用引号引起来.例如:-Dmyname="h

  • IntelliJ IDEA设置JVM运行参数的图文介绍

    目录 前言 配置方式及优先级 代码中配置 对某个Application设置 1 进入IDEA,Run–>Edit Configurations 选中要添加JVM参数的Application idea.exe.vmoption配置文件中更改 优先级 前言 之前看java虚拟机方面的知识,从理论上了解了较多的调优原理及参数,疑惑怎么才能在生产环境中设置这些虚拟机参数,今天特地学习并记录. 之前给大家介绍过几篇关于idea设置JVM运行参数的文章,喜欢的话可以点击阅读. IntelliJ IDEA设置

随机推荐