1.idea设置JVM启动参数
三种设置方式:
- 修改配置文件
(全局配置,优先级低)
idea安装目录下, bin 目录,其中有两个 vmoptions 文件,需针对不同的JDK进行配置:
32 位:idea.exe.vmoptions
64 位:idea64.exe.vmoptions
修改文件的相关参数,重启idea生效。如果不管用,可以在idea中设置help -->Edit Custom VM Options...
。
-Xms128m
-Xmx2048m
-XX:ReservedCodeCacheSize=240m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-Djdk.http.auth.tunneling.disabledSchemes=""
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
- 设置main方法启动参数,集成环境则是设置VM启动参数
(针对某个main方法的jvm,优先级高)
-Xms64m #JVM启动时的初始堆大小
-Xmx128m #最大堆大小
-Xmn64m #年轻代的大小,其余的空间是老年代
-XX:MaxMetaspaceSize=128m #
-XX:CompressedClassSpaceSize=64m #使用 -XX:CompressedClassSpaceSize 设置为压缩类空间保留的最大内存。
-Xss256k #线程
-XX:InitialCodeCacheSize=4m #
-XX:ReservedCodeCacheSize=8m # 这是由 JIT编译器编译为本地代码的本机代码(如JNI)或 Java 方法的空间
-XX:MaxDirectMemorySize=16m
-jar app.jar
2.设置JVM运行参数
JVM内存使用情况查看工具
文章参考地址:http://www.cnblogs.com/jack204/archive/2012/07/02/2572932.html
-
设置JVM内存的参数有四个:
-Xmx
Java Heap最大值,默认值为物理内存的1/4,最佳设值应该视物理内存大小及计算机内其他内存开销而定;
-Xms
Java Heap初始值,Server端JVM最好将-Xms和-Xmx设为相同值
,开发测试机JVM可以保留默认值;
-Xmn
Java Heap Young区(新生代)
大小,不熟悉最好保留默认值;
-Xss
每个线程的Stack大小,不熟悉最好保留默认值; -
如何设置JVM内存分配:
(1)当在命令提示符下启动并使用JVM时(只对当前运行的类Test生效):
java -Xmx128m -Xms64m -Xmn32m -Xss16m Test
(2)当在集成开发环境下(如eclipse)启动并使用JVM时:
a. 在eclipse根目录下打开eclipse.ini,默认内容为(这里设置的是运行当前开发工具的JVM内存分配):
-vmargs
-Xms40m
-Xmx256m
-vmargs表示以下为虚拟机设置参数,可修改其中的参数值,也可添加-Xmn,-Xss,另外,eclipse.ini内还可以设置非堆内存,如:-XX:PermSize=56m,-XX:MaxPermSize=128m。
此处设置的参数值可以通过以下配置在开发工具的状态栏显示:
在eclipse根目录下创建文件options,文件内容为:org.eclipse.ui/perf/showHeapStatus=true
修改eclipse根目录下的eclipse.ini文件,在开头处添加如下内容:
-debug
options
-vm
javaw.exe
重新启动eclipse,就可以看到下方状态条多了JVM信息。
b. 打开eclipse-窗口-首选项-Java-已安装的JRE(对在当前开发环境中运行的java程序皆生效)
编辑当前使用的JRE,在缺省VM参数中输入:-Xmx128m -Xms64m -Xmn32m -Xss16m
c. 打开eclipse-运行-运行-Java应用程序(只对所设置的java类生效)
选定需设置内存分配的类-自变量,在VM自变量中输入:-Xmx128m -Xms64m -Xmn32m -Xss16m
注:如果在同一开发环境中同时进行了b和c设置,则b设置生效,c设置无效,如: 开发环境的设置为:-Xmx256m,而类Test的设置为:-Xmx128m -Xms64m,则运行Test时生效的设置为: -Xmx256m -Xms64m
(3)当在服务器环境下(如Tomcat)启动并使用JVM时(对当前服务器环境下所以Java程序生效):
a. 设置环境变量:
变量名:CATALINA_OPTS
变量值:-Xmx128m -Xms64m -Xmn32m -Xss16m
b. 打开Tomcat根目录下的bin文件夹,编辑catalina.bat,将其中的�TALINA_OPTS%(共有四处)替换为:-Xmx128m -Xms64m -Xmn32m -Xss16m -
查看设置JVM内存信息
JVM实际可用内存 = maxMemory()-totalMemory()+freeMemory()
官方文档见:
http://docs.sun.com/source/819-0084/pt_tuningjava.html
public static void main(String[] args) {
//为JVM的最大可用内存,可通过-Xmx设置,默认值为物理内存的1/4,设值不能高于计算机物理内存;
System.out.println(mb(Runtime.getRuntime().maxMemory()));
//为当前JVM占用的内存总数,其值相当于当前JVM已使用的内存及freeMemory()的总和,会随着JVM使用内存的增加而增加;
System.out.println(mb(Runtime.getRuntime().freeMemory()));
//为当前JVM空闲内存,因为JVM只有在需要内存时才占用物理内存使用,所以freeMemory()的值一般情况下都很小,
// 而 JVM实际可用内存并不等于freeMemory(),而应该等于maxMemory()-totalMemory()+freeMemory()。
System.out.println(mb(Runtime.getRuntime().totalMemory()));
}
static String mb(long s) {
return String.format("%d (%.2f M)", s, (double) s / (1024 * 1024));
}
3.JVM内存区域划分
堆内存
不包括永久代
:
《深入理解Java虚拟机第二版 周志明著》第41页提及到:“方法区与Java堆一样,是各个线程共享的内存区域。它用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据
。虽然java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做非堆
,目的应该是与Java堆区分开来的,在JDK的HotSpot虚拟机中,可以认为方法区就是永久代,但是在其他类型的虚拟机中,没有永久代的概念
// 设置启动参数: -Xmx16m -Xms16m -Xmn5m -XX:PermSize=16m -XX:MaxPermSize=16m -XX:+PrintGCDetails
public static void main(String[] args) {
try {
System.in.read();
}catch (IOException e){
}
}
运用jconsole检测内存占用情况:
11264KB (Old Gen) + 4096KB (Eden Space) + 2* 512KB(Survivor Space) = 16MB
另外,运行-XX
设置永久带(元空间)
的大小不受影响,可能对应JVM参数设置会不同,此类参数是不健壮的,SUN也不推荐使用
另一个实例:
https://blog.csdn.net/u010393809/article/details/53169255
4.JVM启动参数详解
java启动参数共分为三类;
-
标准参数
(-),所有的JVM实现都必须实现这些参数的功能,而且向后兼容;比较有用的有-verbose
,如:
-verbose:class
输出jvm载入类的相关信息,当jvm报告说找不到类或者类冲突时可此进行诊断。
-verbose:gc
输出每次GC的相关情况。
-verbose:jni
输出native方法调用的相关情况,一般用于诊断jni(虚拟机)调用错误信息。 -
非标准参数(-X)
又称为扩展参数,用到的最多,默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足,且不保证向后兼容;
-Xms512m
设置JVM促使内存为512m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
-Xmx512m
,设置JVM最大可用内存为512M。
-Xmn200m
:设置年轻代大小为200M。整个堆大小=年轻代大小 + 年老代大小
。(-Xmn 是将NewSize与MaxNewSize设为一致。200m),同下面两个参数-XX:NewSize=200m -XX:MaxNewSize=200m
。
-Xss128k
:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内 存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
-Xloggc:file
与-verbose:gc功能类似,只是将每次GC事件的相关情况记录到一个文件中,文件的位置最好在本地,以避免网络的潜在问题, 若与verbose命令同时出现在命令行中,则以-Xloggc为准。
-Xprof
: 跟踪正运行的程序,并将跟踪数据在标准输出输出;适合于开发环境调试。 -
非Stable参数(-XX),此类参数各个jvm实现会有所不同,将来可能会随时取消,需要慎重使用;
用-XX作为前缀的参数列表在jvm中可能是不健壮的,SUN也不推荐使用,后续可能会在没有通知的情况下就直接取消了;但是由于这些参数中的确有很多是对我们很有用的,比如我们经常会见到的-XX:PermSize、-XX:MaxPermSize等等;
首先来介绍行为参数:
表格中黑体的三个参数代表着jvm中GC执行的三种方式,即串行、并行、并发;
串行(SerialGC)是jvm的默认GC方式,一般适用于小型应用和单处理器,算法比较简单,GC效率也较高,但可能会给应用带来停顿;
并行(ParallelGC)是指GC运行时,对应用程序运行没有影响,GC和app两者的线程在并发执行,这样可以最大限度不影响app的运行;
并发(ConcMarkSweepGC)是指多个线程并发执行GC,一般适用于多处理器系统中,可以提高GC的效率,但算法复杂,系统消耗较大;
参数及其默认值 | 描述 |
---|---|
-XX:-DisableExplicitGC | 禁止调用System.gc();但jvm的gc仍然有效 |
-XX:+MaxFDLimit | 最大化文件描述符的数量限制 |
-XX:+ScavengeBeforeFullGC | 新生代GC优先于Full GC执行 |
-XX:+UseGCOverheadLimit | 在抛出OOM之前限制jvm耗费在GC上的时间比例 |
-XX:-UseConcMarkSweepGC | 对老生代采用并发标记交换算法进行GC |
-XX:-UseParallelGC | 启用并行GC |
-XX:-UseParallelOldGC | 对Full GC启用并行,当-XX:-UseParallelGC启用时该项自动启用 |
-XX:-UseSerialGC | 启用串行GC |
-XX:+UseThreadPriorities | 启用本地线程优先级 |
-XX:LargePageSizeInBytes=4m | 设置用于Java堆的大页面尺寸 |
-XX:MaxHeapFreeRatio=70 | GC后java堆中空闲量占的最大比例 |
-XX:NewSize=2.125m | 新生代初始大小 |
-XX:MaxNewSize=size | 新生成对象能占用内存的最大值 |
-XX:PermSize=16m | 持久带对象初始内存大小 |
-XX:MaxPermSize=64m | 持久带对象能占用内存的最大值 |
-XX:MinHeapFreeRatio=40 | GC后java堆中空闲量占的最小比例 |
-XX:NewRatio=2 | 新生代内存容量与老生代内存容量的比例,新生代占整个堆内存的2/3 |
-XX:SurvivorRatio=8 | 两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个新生代的1/10 |
-XX:MetaspaceSize=128m (JDK8) | 允许你来限制用于类元数据的本地内存。如果没有特别指定,元空间将会根据应用程序在运行时的需求动态设置大小,默认情况下,类元数据分配受到可用的本机内存容量的限制(容量依然取决于你使用32位JVM还是64位操作系统的虚拟内存的可用性)允许你来限制用于类元数据的本地内存。如果没有特别指定,元空间将会根据应用程序在运行时的需求动态设置大小 |
-XX:MaxMetaspaceSize=512m (JDK8) | 同上 |
-XX:MaxTenuringThreshold=15 | 设置垃圾最大年龄。如果设置为0的话,则新生代对象不经过Survivor区,直接进入老年代。对于老年代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则新生代对象会在Survivor区进行多次复制,这样可以增加对象再新生代的存活时间,增加在新生代即被回收的概论。他最大值为15岁,因为对象头中用了4位进行存储垃圾年龄 【1111(二进制)=15(十进制)】。 |
-XX:ReservedCodeCacheSize=32m | 保留代码占用的内存容量 |
-XX:ThreadStackSize=512 | 设置线程栈大小,若为0则使用系统默认值 |
-XX:+UseLargePages | 使用大页面内存 |
-XX:-CITime | 打印消耗在JIT编译的时间 |
-XX:ErrorFile=./hs_err_pid.log | 保存错误日志或者数据到文件中 |
-XX:-ExtendedDTraceProbes | 开启solaris特有的dtrace探针 |
-XX:HeapDumpPath=./java_pid.hprof | 指定导出堆信息时的路径或文件名 |
-XX:-HeapDumpOnOutOfMemoryError | 当首次遭遇OOM时导出此时堆中相关信息 |
-XX: | 出现致命ERROR之后运行自定义命令 |
-XX:OnOutOfMemoryError=";" | 当首次遭遇OOM时执行自定义命令 |
-XX:-PrintClassHistogram | 遇到Ctrl-Break后打印类实例的柱状信息,与jmap -histo功能相同 |
-XX:-PrintConcurrentLocks | 遇到Ctrl-Break后打印并发锁的相关信息,与jstack -l功能相同 |
-XX:-PrintCommandLineFlags | 打印在命令行中出现过的标记 |
-XX:-PrintCompilation | 当一个方法被编译时打印相关信息 |
-XX:-PrintGC | 每次GC时打印相关信息 |
-XX:-PrintGC Details | 每次GC时打印详细信息 |
-XX:-PrintGCTimeStamps | 打印每次GC的时间戳 |
-XX:-TraceClassLoading | 跟踪类的加载信息 |
-XX:-TraceClassLoadingPreorder | 跟踪被引用到的所有类的加载信息 |
-XX:-TraceClassResolution | 跟踪常量池 |
-XX:-TraceClassUnloading | 跟踪类的卸载信息 |
-XX:-TraceLoaderConstraints | 跟踪类加载器约束的相关信息 |