跟踪垃圾回收:
-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
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" )
}
还可以发现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触发事件
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
栈配置
-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()
directAccess()
}
第一次不算,第二次可见直接内存的访问效率比堆内存快的多。
但是申请分配时间的话,堆空间速度远远快于直接空间
所以:直接空间用于申请分配次数少,但访问频繁的场合。而堆内存适合频繁申请,而不频繁访问的场合。