maxmemory 671mb设置没生效 memory ratio设置_jvm

Java内存基本的调优的调优策略

我们知道GC发生的越频繁,就会对整个系统的性能影响越多。那么如何不频繁的发生GC呢?

存活区空间足够大,老年代空间足够大。就是说内存越大GC发生的频率越低,系统性能就越高。
范例:首先取的可用的内存空间量

public static void main(String[] args) {
 int rat=1024*1024;
 Runtime run=Runtime.getRuntime();
 System.out.println("MAX_MEMORY = "+((double)run.maxMemory()/rat)+"M");
 System.out.println("TOTAL_MEMORY = "+((double)run.totalMemory()/rat)+"M");
 System.out.println("FREE_MEMORY = "+((double)run.freeMemory()/rat)+"M");
}

MAX_MEMORY:默认情况下分配给JVM的最大内存空间,总内存四分之一

TOTAL_MEMORY:默认情况下除了伸缩区之外的可用内存空间

MAX_MEMORY = 1796.0M
TOTAL_MEMORY = 123.0M
FREE_MEMORY = 120.38259887695312M

在整个分配给JVM使用的堆内存之中,TTOTAL表示用户最大可用,而MAX-TOTAL才表示伸缩区。每一块内存都存在一个伸缩区概念,这会造成下面的情况出现:

如果可用内存空间不足,那么会判断是否伸缩区有空间,有就会开辟伸缩区的空间。那么这就会产生开辟和回收的操作部分,进而会产生性能下降问题。
怎么解决呢?

取消伸缩区的概念

maxmemory 671mb设置没生效 memory ratio设置_调优_02


如果现在取消掉伸缩区的概念,初始化内存就设置成最大的可用内存空间,这样就可以实现JVM的性能调整,避免了重复的内存的控制操作,可以提升代码的执行速度。

-Xms:设置初始分配大小,默认为物理内存的“1/64

-Xmx:最大分配内存,默认为物理内存的“1/4”

可以看到默认配置,是“15/64”的内存分配给伸缩区。如果想修改内存的大小(可以使用单位:K、M、G),在本地环境需要考虑到两类情况:

  • IDE修改
-Xms1g -Xmx1g

maxmemory 671mb设置没生效 memory ratio设置_调优_03

MAX_MEMORY = 981.5M

TOTAL_MEMORY = 981.5M

FREE_MEMORY = 971.2599716186523M

可以看到运行结果中,最大分配内存和初始分配内存一样了,这样就取消了伸缩区的概念。

其实,最好是分配内存设置成这样,电脑有64G,保留4G够其他用途,60G分配给Java

  • Java运行修改
java -Xmx1g -Xms1g 类名

在上表中还有一个GC处理详情的查看的参数:-XX:+PrintGCDetails,通过此操作可以详细取得GC处理中的分析过程。
范例:编写一个程序查看GC

public static void main(String[] args) {
 String str="hello";
 while(true){
 str+=str+new java.util.Random(9999999);
 str.intern(); //入池
}
报的异常:java.lang.OutOfMemoryError: Java heap space

运行结果分析

  • 年轻代的处理
[GC (Allocation Failure) 分配失败,意味着当前年轻代没有空间了

[PSYoungGen: 3913K->486K(4608K)] 3913K->1366K(15872K), 0.0024512 secs] [Times: user=0.05 sys=0.00, real=0.00 secs]
  • 老年代的处理
[Full GC (Allocation Failure)此时老年代分配内存失败

[PSYoungGen: 32K->0K(4608K)]

[ParOldGen: 6439K->6436K(11264K)] 6471K->6436K(15872K),

[Metaspace: 3456K->3456K(1056768K)], 0.0088875 secs]

[Times: user=0.05 sys=0.00, real=0.01 secs]
  • 显示出每一块内存空间的内存使用情况
Heap

PSYoungGen total 2560K, used 122K

eden space 2048K, 5% used

from space 512K, 0% used

to space 1536K, 0% used

ParOldGen total 11264K, used 6416K

object space 11264K, 56% used

Metaspace used 3488K, capacity 4496K, committed 4864K, reserved 1056768K

class space used 379K, capacity 388K, committed 512K, reserved 1048576K

监控程序

上面堆内存空间使用情况,实际上只能给开发人员查看,运维看不懂。如果想让运维看,必须使用一些监控程序。Java有两类监控程序,JDK的bin目录下

  • jmap.exe (可以在Linux上运行)

    在命令行执行后,会将整个进程的内存的使用情况整合列出
  • jvisualvm.exe (图形化,不能在linux上看)

    启动后,可以看到IDEA执行的项目

    修改IDEA运行参数 -Xms5G -Xmx5G -XX:+PrintGCDetails ,并启动
    监视可以看到内存占用情况、垃圾回收

    线程可以看到程序中运行的线程

    最后,看一个面试题:你们项目之中是如何对Java(JVM)进行调优的?
在堆内存会存在伸缩区的概念,默认情况下最大可用内存是整体的“1/4”,默认初始使用的内存是“1/64”,
这时只需要避免伸缩区频繁变更就可以提高性能。具体做法:在运行时设置“-Xmx”、“-Xms”大小一样。

最最后,提醒大家一句:性能的调优不是一蹴而就的,项目本身写的非常烂,再怎么调优提升也不大。除此之外,你的电脑内存很大,你希望充分发挥JVM的性能,你可以这样调优。同时,这样调优也是最基本的调优。