理解JVM(3)虚拟机参数

本文介绍了如何使用Java虚拟机选项来跟踪垃圾回收、类的装卸载及查看系统参数等操作,探讨了堆内存配置方法,包括新生代和老年代的调整策略,并提供了内存溢出处理技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

跟踪垃圾回收:

-XX:+PrintGC ->简单GC日志
-XX:+PrintGCDetails ->详细GC日志
-XX:+PrintHeapAtGC ->会在每次GC前后分别打印堆信息
-XX:+PrintGCTimeStamps ->每次GC发生后,输出GC的发生时间
-XX:+PrintGCApplicationConcurrentTime ->打印GC应用程序的执行时间
-XX:+PrintGCApplicationStoppedTime ->打印由于GC而产生的停顿时间
XX:+PrintReferenceGC -> 跟踪系统内的软引用,弱引用,虚引用和Finallize队列
可以使用以日志的形式打印:-Xloggc:log/gc.log

跟踪类的装卸载

-verbose:class ->跟踪类的装卸载
-XX:+TraceClassLoading ->跟踪类的装载
-XX:+TraceClassUnloading ->跟踪类的卸载

查看系统参数

-XX:PrintVMOptions
-XX:PrintFlagsFinal -> 打印所有系统参数的值

堆的配置(包括老年代和新生代)

初始堆的大小-Xms=xxM
最大堆的大小-Xmx=xxM
/*
-Xmx20m -Xms10m
*/
fun main(args: Array<String>) {
    println("maxMemory = ${Runtime.getRuntime().maxMemory()/1024} KB")
    println("freeMemory = ${Runtime.getRuntime().freeMemory()/1024} KB")
    println("totalMemory = ${Runtime.getRuntime().totalMemory()/1024} KB")
    println()

    var MB = ByteArray(1*1024*1024)

    println("maxMemory = ${Runtime.getRuntime().maxMemory()/1024} KB")
    println("freeMemory = ${Runtime.getRuntime().freeMemory()/1024} KB")
    println("totalMemory = ${Runtime.getRuntime().totalMemory()/1024} KB")
    println()

    MB = ByteArray(10*1024*1024)

    println("maxMemory = ${Runtime.getRuntime().maxMemory()/1024} KB")
    println("freeMemory = ${Runtime.getRuntime().freeMemory()/1024} KB")
    println("totalMemory = ${Runtime.getRuntime().totalMemory()/1024} KB")
}

/*
maxMemory = 18432 KB    //-Xmx=20M
freeMemory = 7988 KB    //初始化后剩余的内存
totalMemory = 9728 KB   //-Xmx=10M

maxMemory = 18432 KB
freeMemory = 6964 KB    //分配1MB内存
totalMemory = 9728 KB   //还没有额外分配内存

maxMemory = 18432 KB
freeMemory = 3380 KB    //分配了10MB
totalMemory = 16384 KB  //扩展了内存
*/
还可以发现9728KB, 小于我们分配的10MB,因为垃圾收集算法会分配一块作为from区

新生代的配置(包括eden,from,to区)

-Xmn可以设置新生代的大小,设置较大的新生代会减小老年代的大小。一般设置为堆内存的1/3到1/4
-XX:SurvivorRatio设置eden区和from/to区的比例关系,=eden/from=eden/to,一般为8
-XX:NewRatio=老年代/新生代
大对象在新生代分配不下,会直接分配在老生代,并触发一次新生代GC,对eden区进行部分回收。在实际工作中,尽量将对象留在新生代,减少老年代的GC次数。

堆内存溢出处理,记录错误

-XX:+HeapDumpOutOfMemoryError
-XX:HeapDumpPath=d:/a.dump
-XX:OnOutOfMemoryError触发事件
#printstack.bat
D:/jdk/bin/jstack -F %1 > D:/a.txt

#参数
-Xmx20m -Xms5m "-XX:OnOutOfMemoryError=D:/printstack.bat %p" 
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/a.dump

其他内存区的配置

方法区

JDK1.6,1.7: -XX:PermSize和-XX:MaxPermSize
JDK1.8: -MaxMetaspaceSize

栈配置

-Xss128k: 指定线程的栈大小

直接内存区配置

-XX:MaxDirectMemorySize,不设置则默认为最大堆空间大小
fun directAccess(){
    val t0 = System.currentTimeMillis()
    val b = ByteBuffer.allocateDirect(5000)
    for (i in 0..100000){
        for (j in 0..999){
            b.putInt(j)
        }
        b.flip()
        for (j in 0..999){
            b.getInt()
        }
        b.clear()
    }
    val t1 = System.currentTimeMillis()
    println("Time used:${t1-t0}")
}

fun bufferAccess(){
    val t0 = System.currentTimeMillis()
    val b = ByteBuffer.allocate(5000)
    for (i in 0..100000){
        for (j in 0..999){
            b.putInt(j)
        }
        b.flip()
        for (j in 0..999){
            b.getInt()
        }
        b.clear()
    }
    val t1 = System.currentTimeMillis()
    println("Time used:${t1-t0}")
}

fun main(args: Array<String>) {
    bufferAccess()
    directAccess()

    bufferAccess()   //165
    directAccess()   //55
}
第一次不算,第二次可见直接内存的访问效率比堆内存快的多。
但是申请分配时间的话,堆空间速度远远快于直接空间
所以:直接空间用于申请分配次数少,但访问频繁的场合。而堆内存适合频繁申请,而不频繁访问的场合。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值