场景:
用户反馈,某一模块,闲时正常,一道用户量稍微大点,就会出现卡顿的情况,代码层面已经优化过了N次,数据库也清理出了资源,用户希望快速改善这个问题,因此尝试从JVM的调优来改善。
JAVA内存模型
来源
Java内存管理-JVM内存模型以及JDK7和JDK8内存模型对比总结(三) - 阿飞云 - 博客园
JVM内存:年轻代,老年代,永久代(jdk1.8永久移除,由元空间取代)_LZ_玉米的博客-CSDN博客
Java虚拟机规范(Java SE 7版)
运行时常量池变化
java8内存模型
方法区
方法区在JVM中也是一个非常重要的区域,它与堆一样,是被线程共享的区域。在方法区中,存储了每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码等。方法区是堆的一个逻辑部分,为了区分Java堆,它还有一个别名Non-Heap(非堆)。相对而言,GC对于这个区域的收集是很少出现的。当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。
在Java 7及之前版本,我们也习惯称方法区它为“永久代”(Permanent Generation),更确切来说,应该是“HotSpot使用永久代实现了方法区”!
Java8为什么要将永久代替换成Metaspace?
- 1、字符串存在永久代中,容易出现性能问题和内存溢出。
- 2、类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困 难,太小容易出现永久代溢出,太大则容易导致老年代溢出。
- 3、永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。
- 4、Oracle 可能会将HotSpot 与 JRockit 合二为一。
Java堆
堆是jvm内存管理的最大的一块区域,此内存区域的唯一目的就是存放对象的实例,所有对象实例与数组都要在堆上分配内存。它也是垃圾收集器的主要管理区域。java对可以处于物理上不连续的空间,只要逻辑上是连续的即可。线程共享的区域。如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将抛出OutOfMemoryError异常。
为了支持垃圾收集,堆被分为三个部分:
-
年轻代 : 常常又被划分为Eden区和Survivor(From Survivor To Survivor)区(Eden空间、From Survivor空间、To Survivor空间(空间分配比例是8:1:1)
-
老年代
-
永久代 (jdk 8已移除永久代,取而代之的是另一块与堆不相连的本地内存——元空间)
JVM内存分代
JVM内存分代模型1
JVM内存分代模型2
在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old)。新生代 ( Young ) 又被划分为三个区域:Eden、S0、S1。 这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象,包括内存的分配以及回收。
Java 中的堆也是 GC 收集垃圾的主要区域。GC 分为两种:Minor GC、Full GC ( 或称为 Major GC )。
垃圾回收过程
来源
过程描述
1、首先,将任何新对象分配给eden空间。两个survivor空间都是空的。
2、当eden空间填满时,会触发轻微的垃圾收集。
3、引用的对象被移动到第一个survivor空间。清除eden空间时,将删除为引用的对象。
4、在下一次Minor GC中,Eden区也会做同样的操作。删除未被引用的对象,并将被引用的对象移动到Survivor区。然而,这里,他们被移动到了第二个Survivor区(S1)。此外,第一个Survivor区(S0)中,在上一次Minor GC幸存的对象,会增加年龄,并被移动到S1中。待所有幸存对象都被移动到S1后,S0和Eden区都会被清空。注意,Survivor区中有了不同年龄的对象。
5、在下一次Minor GC中,会重复同样的操作。不过,这一次Survivor区会交换。被引用的对象移动到S0.幸存的对象增加年龄。Eden区和S1被清空。
6、此幻灯片演示了promotion。在较小的GC之后,当老化的物体达到一定的年龄阈值(在该示例中为8)时,它们从年轻一代晋升到老一代。
7、随着较小的GC持续发生,物体将继续被推广到老一代空间。
8、所以这几乎涵盖了年轻一代的整个过程。最终,将主要对老一代进行GC,清理并最终压缩该空间。
一段形象的描述
Jvm区域总体分两类,heap区和非heap区。heap区又分:Eden Space(伊甸园)、Survivor Space(幸存者区)、Tenured Gen(老年代-养老区)。 非heap区又分:Code Cache(代码缓存区)、Perm Gen(永久代)、Jvm Stack(java虚拟机栈)、Local Method Statck(本地方法栈)。
HotSpot虚拟机GC算法采用分代收集算法:
1、一个人(对象)出来(new 出来)后会在Eden Space(伊甸园)无忧无虑的生活,直到GC到来打破了他们平静的生活。GC会逐一问清楚每个对象的情况,有没有钱(此对象的引用)啊,因为GC想赚钱呀,有钱的才可以敲诈嘛。然后富人就会进入Survivor Space(幸存者区),穷人的就直接kill掉。
2、并不是进入Survivor Space(幸存者区)后就保证人身是安全的,但至少可以活段时间。GC会定期(可以自定义)会对这些人进行敲诈,亿万富翁每次都给钱,GC很满意,就让其进入了Genured Gen(养老区)。万元户经不住几次敲诈就没钱了,GC看没有啥价值啦,就直接kill掉了。
3、进入到养老区的人基本就可以保证人身安全啦,但是亿万富豪有的也会挥霍成穷光蛋,只要钱没了,GC还是kill掉。
JVM常用参数
来源
JVM常用基础参数-栈内存Xss讲解_泷泷养的乔小胖-CSDN博客_jvm xss
-Xms 初始堆内存大小,默认物理内存64/1
-Xms = -XX:InitialHeapSize
-Xmx 最大堆内存,默认物理内存4/1
-Xmx = -XX:MaxHeapSize
-Xss 栈内存大小
设置单个线程栈大小,一般默认512~1024kb。
单个线程栈大小跟操作系统和JDK版本都有关系
-Xss = -XX:ThreadStackSize
-Xmn 年轻代大小
-XX:MetaspaceSize 元空间大小
元空间本质跟永久代类似,都是对JVM规范中方法区的实现。
不过元空间与永久代最大的区别在于:元空间并不在虚拟机中,而是使用本机内存。
因此,元空间大小仅受本地内存限制。
-XX:MetaspaceSize 初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值
-XX:MaxMetaspaceSize 最大空间,默认是没有限制的
-XX:MinMetaspaceFreeRatio 在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集
-XX:MaxMetaspaceFreeRatio 在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集-XX:+PrintGCDetails 打印GC详细日志信息
-XX:SurvivorRatio 幸存者比例设置
2个Survivor区(From幸存区或To幸存区)和Eden区的比值
-XX:NewRatio 新生代比例设置
新生代(Eden + 2*S)与老年代(不包括永久区)的比值
-XX:MaxTenuringThreshold 进入老年代阈值设置
JVM监控分析
来源
dump分析工具_JVM实战:JVM常用监控工具_weixin_39757169的博客-CSDN博客
在线监控工具
JPS (打印Java进程信息)
常用命令: jps -l
Jstat (JVM统计信息)
使用场景 :用于查看各个功能和区域的统计信息(如:类加载、编译相关信息统计,各个内存区域GC概况和统计)
格式 : jstat 【选项】 【进程ID】 [间隔时间/毫秒 ] [查询次数]
常用指令:jstat -gc PID
查看即时内存使用情况、垃圾回收统计信息,用于分析GC情况。
指令: jstat -gc 16462 1000 5
//查看16462进程 应用的堆内存使用、垃圾回收统计信息,每个1000毫秒输出一次,总共输入5次 。
参数说明
S0C 和 S0U //S0区的总内存大小和已使用的内存大小。
S1C: 和S1U //S1区的总内存大小和已使用的内存大小。。
EC 和 EU //Eden区的总内存大小 和已使用的内存大小。
OC和OU //Old区的总内存大小 和已使用的内存大小。
MC和MU //方法区的总内存大小 和已使用的内存大小。
CCSC和CCSU //压缩类空间大小 和已使用的内存大小。
YGC和 YGCT //Young GC 的总次数 和消耗总时间。
FGC和 FGCT //Full Gc的总次数和消耗总时间。
GCT //所有GC的消耗时间。
jvm耗时和频率计算
来源
java ygc 频繁_jvm之判断ygc耗时和频率_琥蛮的博客-CSDN博客
ygc平均耗时=YGCT/YGC(s)
ygc时间间隔=程序的运行时间/YGC
fgc平均耗时=FGCT/FGC(s)
fgc时间间隔=程序的运行时间/FGC
程序运行总时间查看
ps -p {pid} -o etime
总结
如果各项参数设置合理,系统没有超时日志出现,GC频率不高,GC耗时不高,那么没有必要进行GC优化;如果GC时间超过1?3 秒,或者频繁G C ,则必须优化。如果满足下面的指标,则一般不需要进行GC调整。
Jinfo(JVM参数查看修改)
使用场景: 查看和调整JVM启动和运行参数。
案例一:查看JVM整个系统参数信息
比如:输出16462进程jvm的全部参数和系统属性。
指令 : jinfo 16462
案列二: 查看某个具体参数
比如:查看老年代内存大小
指令:jinfo -flag OldSize 16462
案列三:启用某个配置
比如:开启堆内存溢出日志打印(默认是关闭的)。
指令:jinfo -flag +PrintGCDetails 16462
案例四:修改某个参数值
比如:修改当堆内存对象所占空间超过80%时进行扩容
指令:jinfo -flag MaxHeapFreeRatio=80 16462
案列五:启用某个配置
比如: 启动GC日志打印
指令:jinfo -flag +PrintGCDetails 16462
Jmap(JVM内存信息监控)
使用场景: 监控堆内存使用情况和对象占用情况, 生成堆内存快照文件,查看堆内存区域配置信息。注意生产环境中如果程序的堆占用内存已经很大的话,不建议用这个分析。
格式:jmap 【选项】【进程ID】
案例一:查看堆内存的配置和使用情况
jmap -heap 18230
Heap Configuration:
MinHeapFreeRatio = 0 //JVM堆缩减空间比率,低于则进行内存缩减
MaxHeapFreeRatio = 100 //JVM堆扩大内存空闲比例,高于则进行内存扩张
MaxHeapSize = 994050048 (948.0MB) //堆最大内
NewSize = 20971520 (20.0MB) //新生代初始化内存大小
MaxNewSize = 331350016 (316.0MB) //新生代最大内存大小
OldSize = 41943040 (40.0MB) //老年代内存大小
NewRatio = 2 //新生代和老年代占堆内存比率
SurvivorRatio = 8 //s区和Eden区占新生代内存比率
MetaspaceSize = 21807104 (20.796875MB) //元数据初始化空间大小
CompressedClassSpaceSize = 1073741824 (1024.0MB) //类指针压缩空间大小
MaxMetaspaceSize = 17592186044415 MB //元数据最大内存代销
G1HeapRegionSize = 0 (0.0MB) //G1收集器Region单元大小
Heap Usage:
PS Young Generation
Eden Space:
capacity = 303038464 (289.0MB) //Eden区总容量
used = 22801000 (21.744728088378906MB) //Eden区已使用荣浪
free = 280237464 (267.2552719116211MB) //Eden区剩余容量
7.524127366221075% used //Eden区使用比例
From Space: //From区(也就是Survivor中的S1区)
capacity = 13107200 (12.5MB) //S1区总容量大小
used = 5364536 (5.116020202636719MB) //S1区已使用大小
free = 7742664 (7.383979797363281MB) //S1区剩余大小
40.92816162109375% used //S1使用比例
To Space: //To区 (也就是Survivor中的S2区)
capacity = 13631488 (13.0MB) //S2区总容量大小
used = 0 (0.0MB) //S2区已使用大小
free = 13631488 (13.0MB) //S2区剩余大小
0.0% used //S2区使用比率
PS Old Generation
capacity = 110624768 (105.5MB) //老年代总容量大小
used = 49431224 (47.14128875732422MB) //老年代已使用大小
free = 61193544 (58.35871124267578MB) //老年代剩余大小
44.68368602589973% used //老年代使用功能比例
案例二:查看JVM中对应类型对象的数量、占用内存情况
统计实例最多的类 前十位有哪些
jmap -histo 18230 | sort -n -r -k 2 | head -10
统计合计容量前十的类有哪些
jmap -histo 18230 | sort -n -r -k 3 | head -10
案例三:dump 堆快照
命令:jmap -dump:live,format=b,file=/home/myheapdump.hprof 18230
live 加上live代表只dump存活的对象 ;
fomat 格式
filie 导出的文件名
18230 java进程ID
这里生成的 dump文件可以用我们后面讲的可视化工具VisualVM来打开文件对里面的内容进行分析。
VisualVM分析dump文件
来源
用jvisualvm分析dump文件_huangpeigui的专栏-CSDN博客_jvisualvm分析dump文件
注意装入时候选择的文件类型
VisualVM插件安装
来源
jvisualvm 无法下载插件解决方案_xixingzhe2的博客-CSDN博客
url地址:
https://visualvm.github.io/pluginscenters.html
选择对应版本的地址进入
复制Catalog URL
插件中心配置
将复制的地址拷贝到插件中心的地址中
第三方在线监控工具(Arthas)
Arthas
是Alibaba开源的Java诊断工具,它可以帮助我们解决在线环境的以下问题
- 监控到JVM的实时运行状态(涵盖Jps ,jstat ,jinfo ,jstack ,部分Jmap功能)。
- 在不需要重新部署服务的情况下修改业务代码。
- 以局视角来查看系统的运行状况。
JVM调优总结
GC大致流程
来源:
JVM GC调优一则--增大Eden Space提高性能_anningzhu的博客-CSDN博客
大部分新对象在Eden Space上分配,当Eden Space满了,则要用到Survivor Space来回收。YGC的算法是很快的。
多次YGC之后,还存活的对象就会被移到Old Generation(old space)上,当Old Generation满了的时候,就会FGC,FGC有通常比较慢。
Permanent Space只要你在开始时分配了足够大的空间,那它可以不用管
理想的GC/内存使用情况:
Old Space增长缓慢,FullGC次数少,FullGC的时间短(大部情况应该要在1秒内)。
总结:
尽量少加上一些默认参数。这点我很赞同RednaxelaFX的看法,配置了默认参数除了让后面调优的人蛋疼之外,没有太多的帮助。
GC调优就是一个取舍权衡的过程,有得必有失,最好可以在多个不同的实例里,配置不同的参数,然后进行比较。
尽可能最小化"短暂对象"移动到老年代的数量,同时最小化年轻代GC的次数和持续时间,要找到适当的折衷方案,首先要了解应用程序中对象年龄的分布情况。
有很多命令行工具或者图形工具可以使用,好的工具事半功倍。
调优总结:
1.新生代(Young generation)的空间太小,导致有一些本应该可以很快就被回收的对象被放到了老生代(Old generation)里,导致老生代上涨很快,频繁Full GC
2.内存泄露(Memory Leak):程序在申请内存后,对象没有被GC所回收,它始终占用内存,内存泄漏的堆积最终会造成内存溢出。
3.内存溢出(Memory Overflow):程序运行过程中无法申请到足够的内存而导致的一种错误。内存溢出通常发生于OLD段或Perm段垃圾回收后,仍然无内存空间容纳新的Java对象的情况。通常都是由于内存泄露导致堆栈内存不断增大,从而引发内存溢出。
4.如果Eden区域设置太大
新生成的对象会被分配在Eden区,Eden空间不足时会触发MinorGC。理想状态下,如果所有对象在这个阶段全部被回收,Eden区域被清空,不会出什么问题。如果GC后还存在一部分幸存的对象,则会被复制到To Survivor区域,此时因为Survivor区域空间太小无法容纳这些对象,结果大部分幸存对象只在进行一次或很少次的GC后就会被移动到老年代,也就是说从某种程度上来讲失去了MinorGC的初衷,这种情况是肯定不被允许的。
5.Eden区域设置太小
Eden区域设置太小,意味着其空间很快就会被占满,也就是说增加了新生代的GC次数,而频繁的GC会降低整体JVM性能。
6.年轻代大小选择
响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对象。
吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度。因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用。
7.年老代大小选择
响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间。最优化的方案,一般需要参考以下数据获得:
并发垃圾收集信息
持久代并发收集次数
传统GC信息
花在年轻代和年老代回收上的时间比例
减少年轻代和年老代花费的时间,一般会提高应用的效率
吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。
8.较小堆引起的碎片问题
因为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象。但是,当堆空间 较小时,运行一段时间以后,就会出现“碎片”,如果并发收集器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记、清除方式进行回收。如果出 现“碎片”,可能需要进行如下配置:
-XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩。
-XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩。
来源:JVM调优总结 + jstat 分析【转】 - daddy再出发 - 博客园
9 Full GC过多
出现full gc的原因多是慢处理和高并发
(1)内存分配不合理,导致对象频繁进入老年代,进而引发频繁的Full GC;
(2) 存在内存泄漏等问题,就是内存里驻留了大量的对象塞满了老年代,导致稍微有一些对象进入老年代就会引发Full GC;
(3) 永久代里的类太多,触发了Full GC
导出dump文件
jmap -dump:live,format=b,file=/home/server/heap.bin 55025
使用mat分析
https://www.eclipse.org/mat/downloads.php
10. cpu过高
(1)一般是创建过多线程并发执行,且工作负载都很重,
(2) 频繁full gc
11.堆内存溢出
原因:高并发,慢查询
12.永久代(元空间)内存溢出
原因:使用字节码技术生产了太多的类
13.OOM处理排查
我们可以让JVM在OOM时dump一份内存快照,事后我们只要分析这个内存快照,一下就可以知道是哪些可恶的对象占用了所有的内存,并且还无法释放。
-XX:+HeapDumpOnOutOfMemoryError 在OOM的时候自动dump内存快照出来
-XX:HeapDumpPath=/usr/local/app/oom 把内存快照放到哪儿去
14.内存耗费过高
内存耗费超过50%感到有点惊讶,因为这说明他几乎快要把分配给他的内存消耗殆尽了!
1 在内存使用这么高的情况下会发生什么?
第一种:是内存使用率居高不下,导致频繁的进行full gc,gc带来的stop the world问题影响了服务。
第二种:是内存使用率过多,导致JVM自己发生OOM。
第三种:是内存使用率过高,也许有的时候会导致这个进程因为申请内存不足,直接被操作系统把这个进程给杀掉了!
15.常见内存溢出
(1) java.lang.OutOfMemoryError: Java heap space —-JVM Heap(堆)溢出
解决方法:手动设置 JVM Heap(堆)的大小。
(2) java.lang.OutOfMemoryError: PermGen space —- PermGen space溢出。
解决方法: 手动设置 MaxPermSize 大小
(3) java.lang.StackOverflowError —- 栈溢出
解决方法:修改程序。
(4)java.lang.StackOverflowError异常
解决方法:Java中,栈的大小通过-Xss来设置,当栈中存储数据比较多时,需要适当调大这个值
来源
Tomcat的JVM调优
来源:
修改Tomcat使用的JVM内存大小_翻越山峰-CSDN博客_tomcat修改jvm内存大小
文件配置
Linux下修改JVM内存大小:
要添加在tomcat 的bin 下catalina.sh 里,位置cygwin=false前 。注意引号要带上,红色的为新添加的.
# OS specific support. $var _must_ be set to either true or false.
JAVA_OPTS="-Xms256m -Xmx512m -Xss1024K -XX:PermSize=128m -XX:MaxPermSize=256m"
cygwin=false
windows下修改JVM内存大小:
情况一:解压版本的Tomcat, 要通过startup.bat启动tomcat才能加载配置
要添加在tomcat 的bin 下catalina.bat 里
rem Guess CATALINA_HOME if not defined
set CURRENT_DIR=%cd%后面添加,红色的为新添加的.
set JAVA_OPTS=-Xms256m -Xmx512m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m -Djava.awt.headless=true
推荐JVM优化参数
来源:
tomcat jvm参数优化 - Jasper_boy - 博客园
CATALINA_OPTS="
-Xms2g #初始堆大小
-Xmx2g #最大堆大小
-Xss512k #线程栈大小,出现java.lang.StackOverflowError时增大此值
-Xmn1000m #年轻代大小,对半分
-XX:MetaspaceSize=128m #元数据类存储空间大小,存储与系统内存
-XX:MaxMetaspaceSize=512m #最大元数据类存储空间大小
-Xloggc:/usr/local/tomcat/logs/gc.log #记录gc日志路径
-XX:+PrintGCDetails #打印gc日志
-XX:+PrintGCDateStamps #打印gc发生的具体时间
-XX:+PrintPromotionFailure #打开了就知道是多大的新生代晋升到老生代引发的full gc
-XX:-UseBiasedLocking #取消偏向锁
-XX:AutoBoxCacheMax=20000 #增大Integr cache
-XX:+AlwaysPreTouch #启动时访问并置零内存页面
-Djava.security.egd=file:/dev/./urandom #此江湖偏方原因为Tomcat的SecureRandom显式使用SHA1PRNG算法时,初始因子默认从/dev/random读取会存在堵塞。额外效果是SecureRandom的默认算法也变成合适的SHA1了
-XX:+ExplicitGCInvokesConcurrent #full gc时,使用CMS算法,不是全程停顿,必选
-XX:+ParallelRefProcEnabled #并行的处理Reference对象,如WeakReference,默认为false,除非在GC log里出现Reference处理时间较长的日志,否则效果不会很明显,但我们总是要JVM尽量的并行,所以设了也就设了
-XX:+UseConcMarkSweepGC #老年代并发收集,CMS gc
-XX:CMSInitiatingOccupancyFraction=75 #老年代内存空间使用到75%时执行CMS收集,以确保年老代有足够的空间接纳来自年轻代的对象,避免Full GC的发生。
-XX:+UseCMSInitiatingOccupancyOnly #在年老代使用了初始化的比例后并发收集器启动收集
-XX:-CMSClassUnloadingEnabled #在CMS中清理永久代中的过期的Class而不等到Full GC
-XX:+CMSScavengeBeforeRemark
-XX:+HeapDumpOnOutOfMemoryError #发生OOM时创建堆内存转储文件
-XX:HeapDumpPath=/usr/local/tomcat/logs #发生OOM时创建堆内存转储文件路径,在容器环境中,输出4G的HeapDump在普通硬盘会造成20秒以上的硬盘IO跑满,容易影响同一宿主机上所有其它容器
-XX:OnOutOfMemoryError=/usr/local/tomcat/bin/stop.sh #发生OOM记录内存转储文件后。执行的操作,可以重启或者停止服务
-XX:ErrorFile=/usr/local/tomcat/logs/hs_err_%p.log #jvm crash时hotspot会生成一个error文件,提供jvm状态信息
-XX:+PrintCommandLineFlags #将启动参数输出到catalina.out
-XX:+PrintFlagsFinal #启动后打印默认和更改过的参数值到catalina.out
-XX:-OmitStackTraceInFastThrow
-Duser.timezone=Asia/Shanghai #用户所在时区
-Djavax.servlet.request.encoding=UTF-8
-Djavax.servlet.response.encoding=UTF-8
-Dfile.encoding=UTF-8
-Duser.country=CN
-Duser.language=zh
-Djava.awt.headless=true
-Dcom.sun.management.jmxremote.port=1099 #以下参数为开启jmx远程给监控系统连接
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Djava.rmi.server.hostname=127.0.0.1"