一、题目相关参数
-Xms200m
,表示分配200M-Xms500m
,表示jvm进程最多只能够占用500M内存通常, -Xms
和 -Xmx
设置成一样的,避免每次垃圾回收完成后JVM重新分配内存。因为当Heap不够用时,发生内存抖动,影响程序运行稳定性。
准确来说,是 jvm 可生产线程数的数量,由三个方面影响:
增大堆内存(-Xms,-Xmx)会减少可创建的线程数量;增大线程栈内存(-Xss,32 位系统中此参数值最小为 60 K)也会减少可创建的线程数量。因此题中, -Xmx
加大,Heap内存增大,jvm 空闲的内存数(java虚拟机栈等)就更少,那么可以创建的线程也就更少。
系统从以下几个方面影响最大线程数:
具体影响过程参考 https://blog.csdn.net/moonpure/article/details/80701878
java.lang.Runtime 类中的 freeMemory(), totalMemory(), maxMemory() 这几个方法反映的都是 java 这个进程的内存情况,跟操作系统的内存根本没有关系。
返回的是java虚拟机(这个进程)能够从操作系统那里挖到的最大的内存,以字节为单位,如果在运行 java 程序的时候,没有添加 -Xmx 参数,那么就是 64 M,也就是说 maxMemory() 返回的大约是6410241024 字节,这是 java 虚拟机默认情况下能从操作系统那里挖到的最大的内存。如果添加了 -Xmx 参数,将以这个参数后面的值为准,例如 java-cp you_classpath-Xmx512myour_class
,那么最大内存就是 51210241024 字节。
返回的是 java 虚拟机现在已经从操作系统那里挖过来的内存大小,也就是java虚拟机这个进程当时所占用的所有内存。如果在运行 java 的时候没有添加 -Xms 参数,那么,在 java 程序运行的过程的,内存总是慢慢的从操作系统那里挖的,基本上是用多少挖多少,直到挖到 maxMemory() 为止,所以totalMemory() 是慢慢增大的。如果用了 -Xms 参数,程序在启动的时候就会无条件的从操作系统中挖 -Xms后面定义的内存数,然后在这些内存用的差不多的时候,再去挖。
刚才讲到如果在运行java的时候没有添加 -Xms 参数,那么,在 java 程序运行的过程的,内存总是慢慢的从操作系统那里挖的,基本上是用多少挖多少,但是 java 虚拟机100%的情况下是会稍微多挖一点的,这些挖过来而又没有用上的内存,实际上就是 freeMemory(),所以freeMemory()的值一般情况下都是很小的,但是如果你在运行 java 程序的时候使用了 -Xms,这个时候因为程序在启动的时候就会无条件的从操作系统中挖 -Xms 后面定义的内存数,这个时候,挖过来的内存可能大部分没用上,所以这个时候 freeMemory() 可能会有些大。
JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统下,一般限制在1.5G~2G;64为操作系统对内存无限制。我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m。
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k-Xmx3550m # 设置JVM最大可用内存为3550M。-Xms3550m # 设置JVM促使内存为3550m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。-Xmn2g # 设置年轻代大小为2G。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小 。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。-Xss128k # 设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
依据的原则是根据Java Performance里面的推荐公式来进行设置。
具体来讲:
BTW:
1、Sun官方建议年轻代的大小为整个堆的3/8左右, 所以按照上述设置的方式,基本符合Sun的建议。
2、堆大小=年轻代大小+年老代大小, 即 xmx=xmn+老年代大小 。Permsize不影响堆大小。
3、为什么要按照上面的来进行设置呢?没有具体的说明,但应该是根据多种调优之后得出的一个结论。
具体调整策略参考 https://blog.csdn.net/losetowin/article/details/78569001
JVM给了三种选择:串行收集器、并行收集器、并发收集器 ,但是串行收集器只适用于小数据量的情况,所以这里的选择主要针对并行收集器和并发收集器。默认情况下,JDK5.0以前都是使用串行收集器,如果想使用其他收集器需要在启动时加入相应参数。JDK5.0 以后,JVM会根据当前系统配置
如上文所述,并行收集器主要以到达一定的吞吐量为目标,适用于科学技术和后台处理等。
典型配置 :
java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20-XX:+UseParallelGC # 选择垃圾收集器为并行收集器。此配置仅对年轻代有效。即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集。-XX:ParallelGCThreads=20 # 配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。
如上文所述,并发收集器主要是保证系统的响应时间,减少垃圾收集时的停顿时间。适用于应用服务器、电信领域等。典型配置 :
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC-XX:+UseConcMarkSweepGC # 设置年老代为并发收集。测试中配置这个以后,-XX:NewRatio=4的配置失效了,原因不明。所以,此时年轻代大小最好用-Xmn设置。-XX:+UseParNewGC # 设置年轻代为并行收集。可与CMS收集同时使用。JDK5.0以上,JVM会根据系统配置自行设置,所以无需再设置此值。
-XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:filename
-XX:ParallelGCThreads=n :设置并行收集器收集时使用的CPU数。并行收集线程数。-XX:MaxGCPauseMillis=n :设置并行收集最大暂停时间 -XX:GCTimeRatio=n :设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
-XX:+CMSIncrementalMode :设置为增量模式。适用于单CPU情况。-XX:ParallelGCThreads=n :设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。
https://www.cnblogs.com/ceshi2016/p/8447989.html
https://blog.csdn.net/moonpure/article/details/80701878