【JAVA优化编程】内存管理之——(9)JVM内存参数调优

本文介绍了如何通过调整JVM内存参数来优化应用程序性能,包括设置堆内存大小、新对象生成区比例等关键参数,同时探讨了不同编译方式对类文件大小的影响。

9  JVM内存参数调优

我们前面所提到的堆内存(heap)是由Java虚拟机控制管理的,因此,这些参数对JVM而言都有一个默认值,但在某些情况下这些参数的默认值并不是最优的,这就需要我们通过调整这些参数的值来提高JVM的性能,最终提高应用的性能指标。
在实际的应用开发中,如果应用所使用的系统内存较大,经常会引发内存溢出的错误:
…
java.lang.OutOfMemoryError <<no stack trace available>>
java.lang.OutOfMemoryError <<no stack trace available>>
    Exception in thread "main"
…
这可能是因为应用要使用的堆内存(heap)超过了JVM所管理内存范围,如果我们适当追加内存值有时就可以避免这种致命错误的出现。
在WINDOWS系统上你可以通过参数-verbosegc查看JVM回收内存的信息,在HP UNIX系统上你可以通过-Xverbosegc:file=/tmp/gc$$.out参数将信息重定向到一个文件中。然后查看相应的信息,例如下面的这个类。
public class A {
    public static void main(String args[]) {
        for (int i =0 ;i < 100000;++i) {
            A a = new A();
        }
        System.out.println("this is a GC test");
    }
}
在类A的main方法中创建了100 000个A对象,然后我们看一下JVM回收内存的情况,编译并执行这个类:
>java -verbosegc A
[GC 512K->91K(1984K), 0.0027537 secs]
this is a  GC test
从输出信息中可以看出总共有1984KB的内存被回收,耗时0.002 753 7秒。现在我们将类A添加一行清除对象引用的代码:
public class A {
    public static void main(String args[]) {
        for (int i =0 ;i < 100000;++i) {
            A a = new A();
            a = null;
        }
        System.out.println("this is a GC test");
    }
}
编译并执行这个类:
>java -verbosegc A
[GC 512K->91K(1 984K), 0.0 027 450 secs]
this is a  GC test
我们看到被回收内存的数量并没有变化, 但是回收所需要的时间却变成了0.002 745 0秒,后者比前者节省了0.000 008 7秒,千万不要小看这0.000 008 7秒,当你的应用足够复杂时这个时间就会成指数级增长,看来我们主动清除对象引用的方法,确实可以加速JVM对垃圾内存的回收。
如果再在类A中加入一行强制系统内存回收的代码,结果又会怎样呢?如下所示:
public class A {
    public static void main(String args[]) {
        for (int i =0 ;i < 100000;++i) {
            A a = new A();
            a = null;
        }
        System.gc();
        System.out.println("this is a GC test");
    }
}
编译并执行这个类:
>java -verbosegc A
[GC 512K->91K(1984K), 0.0 027 272 secs]
[Full GC 487K->91K(1984K), 0.0 070 730 secs]
this is a  GC test
系统这次做了两次内存回收,第一次是程 序中强制系统内存回收的代码System.gc()导致的内存回收,而后者是系统最终的内存回收操作,我们看到强制内存回收耗时不长,可是却导致了系统最 终垃圾回收的时间加长了很多,因此我们在采用强制系统垃圾回收(通过显式调用方法System.gc())的办法来回收系统垃圾内存的办法,还是存在一些 弊端的,应尽量少用,或者说只在必要的时候应用。
上面我们提到的内存回收操作就是回收JVM所管理的堆内存(heap)。当系统 连续申请内存并且超过JVM所管理的堆内存(heap)的最大值时,就会产生系统内存溢出的致命异常,下面我们来看一下怎样通过设置JVM的内存参数来优 化JVM对内存的管理,避免内存溢出异常的发生。下表所示的就是与JVM内存相关的参数及其说明。
与JVM内存相关的参数及其说明
JVM 堆内存 heap 设置选项
参数格式 说明
设置新对象生产堆内存(Setting the Newgeneration heap size)
-XX:NewSize
过这个选项可以设置 java 新对象生产堆内存在通常情况下这个选项的数值为 1024的整 数倍并且大于1MB 这个值的取值规则为,一般情况下这个值-XX:NewSize 是最大堆内存(maximum heap size) 的四分之一。增加这个选项值的大小是为了增大较大数量的短生命周期对象
增加Java新对 象生产堆内存相当于增加了处理器的数目并且可以并行地分配内存,但是请注意内存的垃圾回收却是不可以并行处理的
设置最大新对象生产堆内存(Setting the maximum New generation heap size)
-XX:MaxNewSize
通过这个选项可以设置最大Java 新对象生产堆内存通常情况下这个选项的数值为1024 整数倍并且大于1MB
其功用与上面的设置新对象生产堆内存-XX:NewSize 相同
设置新对象生产堆内存的比例(Setting New heap size ratios)
-XX:SurvivorRatio
新对象生产区域通 常情况下被分为3 个子区域:伊甸园,与两个残存对象空间, 这两个空间的大小是相同的通过用-XX:SurvivorRatio=X 选项配置伊甸园与残存对象空间(Eden/survivor) 的大小的比例。 你可以试着将这个值设置为8 然后监控、观察垃圾回收的工作情况
设置堆内存池的最小值(Setting minimum heap size)
-Xms
通过这个选项可以要求系统为堆内存池分配内存空间的最小值通常情况下这个选项的数值为1024的整数倍并且大于1MB 这个值的取值规则为,一般情况下这个值(-Xms) 与最大堆内存相同,以降低垃圾回收的频度
设置堆内存池的最大值 (Setting maximum heap size)
-Xmx
通过这个选项可以要求系统为堆内存池分配内存空间的最大值通常情况下这个选项的数值为1024 的整数倍并且大于1MB。
一般情况下这个值 (-Xmx)与最小堆内存(minimum heap size -Xms) 相同,以降低垃圾回收的频度
取消垃圾回收 -Xnoclassgc 这个选项用来取消系统对特定类的垃圾回收。它可以防止当这个类的所有引用丢失之后,这个类仍被引用时不会再一次被重新装载,因此这个选项将增大系统堆内存的空间
设置栈内存的大小 -Xss
这个选项用来控制本地线程栈的大小当这个选项被设置的较大(>2MB) 时将会在很大程度上降低系统的性能因此在设置这个值时应该格外小心,调整后要注意观察系统的性能,不断调整以期达到最优
根据上表中所描述的参数意义,我们可以在启动应用时为JVM设置相应的参数值以提高系统的性能,如下所示:
java -XX:NewSize=128m -XX:MaxNewSize=128m -XX:SurvivorRatio=8  -Xms512m
-Xmx512m MyApplication

类文件(.class)的大小
由Java源文件.java文件编译成JVM可解释执行的Java字节文 件.class。因所采用的编译方式的不同而大小也不同。通常.class文件的大小也存在是否占用较大内存的问题。通过降低.class文件的大小,不但可以降低系统内存的开销,而且还可以节省网络开销,虽然这部分内容与JVM内存管理联系不大,但是我觉得还是有必要提一下,因为这在你开发Applet应用 时会有帮助。因为一般来说,Applet应用都是靠网络分布式传输 由客户端浏览器装载运行的,如果类文件较大,无疑将会增大网络开销,降低传输速度无法满足用户的需求,并且如果类文件较大,无疑也会消耗客户端内存资源。 我们可以通过在Java编译器javac中添加相应的参数,来缩小类文件的大小,解决上面的问题。
通常有三种编译方式会影响类文件的大小。
(1)默认编译方式:  javac   A.java。
(2)调试编译方式:  javac  –g A.java。
(3)代码编译方式:  javac  –g:none A.java。
例如如下所示的简单的类A:
public class A {
    public static void main(String args[]) {
        for (int i =0 ;i < 100000;++i) {
            A a = new A();
        }
    }
}
通过上面这三种方式编译后的类文件的大小分别为:
默认编译方式:291字节。
调试编译方式:422字节。
代码编译方式:207字节。
采用三种不同的方式,编译产生的类文件的大小差异非常大,这是什么原因导致的呢?原来在于.class文件中包含多个不同的部分或属性。
代码(Code)属性包含实际的方法字节码。源文件信息(SourceFile Information)包含用于生成.class的源文件名称。代码行序号表(LineNumberTable)用来映射源文件中的代码行序号与字节码 文件中的序号偏移。本地变量表(LocalVariableTable)用来映射本地变量与栈桢的偏移。

 注意    如果你想了解字节码文件.class的文件结构详细信息,请参考相关的技术资料,这里就不详细讲解了。

正是由于上面这三种编译方式生成的类文件所包含的信息不同,才导致了类文件的大小差异较大,其包含的信息分别如下所示。
默认编译方式: 代码(Code)、源文件信息(SourceFile Information)、代码行序号表(LineNumberTable)。
调试编译方式: 代码(Code)、源文件信息(SourceFile Information)、代码行序号表(LineNumberTable)、本地变量表(LocalVariableTable)。
代码编译方式: 代码(Code)。
这就是三种编译方式产生类文件大小不同的根本原因。而这三种编译方式在程序开发的不同阶段却都起着非常重要的作用,例如,调试编译方式在程序的调试开发过程中应采用,以获取更为详细的调试信息。因此具体应用上面的三种编译方式中的哪一种,应该适时而定。
基于遗传算法的新的异构分布式系统任务度算法研究(Matlab代码实现)内容概要:本文档围绕基于遗传算法的异构分布式系统任务度算法展开研究,重点介绍了一种结合遗传算法的新颖优化方法,并通过Matlab代码实现验证其在复杂度问题中的有效性。文中还涵盖了多种智能优化算法在生产度、经济度、车间度、无人机路径规划、微电网优化等领域的应用案例,展示了从理论建模到仿真实现的完整流程。此外,文档系统梳理了智能优化、机器学习、路径规划、电力系统管理等多个科研方向的技术体系与实际应用场景,强“借力”工具与创新思维在科研中的重要性。; 适合人群:具备一定Matlab编程基础,从事智能优化、自动化、电力系统、控制工程等相关领域研究的研究生及科研人员,尤其适合正在开展优化、路径规划或算法改进类课题的研究者; 使用场景及目标:①学习遗传算法及其他智能优化算法(如粒子群、蜣螂优化、NSGA等)在任务度中的设计与实现;②掌握Matlab/Simulink在科研仿真中的综合应用;③获取多领域(如微电网、无人机、车间度)的算法复现与创新思路; 阅读建议:建议按目录顺序系统浏览,重点关注算法原理与代码实现的对应关系,结合提供的网盘资源下载完整代码进行试与复现,同时注重从已有案例中提炼可迁移的科研方法与创新路径。
【微电网】【创新点】基于非支配排序的蜣螂优化算法NSDBO求解微电网多目标优化度研究(Matlab代码实现)内容概要:本文提出了一种基于非支配排序的蜣螂优化算法(NSDBO),用于求解微电网多目标优化度问题。该方法结合非支配排序机制,提升了传统蜣螂优化算法在处理多目标问题时的收敛性和分布性,有效解决了微电网度中经济成本、碳排放、能源利用率等多个相互冲突目标的优化难题。研究构建了包含风、光、储能等多种分布式能源的微电网模型,并通过Matlab代码实现算法仿真,验证了NSDBO在寻找帕累托最解集方面的越性能,相较于其他多目标优化算法表现出更强的搜索能力和稳定性。; 适合人群:具备一定电力系统或优化算法基础,从事新能源、微电网、智能优化等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于微电网能量管理系统的多目标优化度设计;②作为新型智能优化算法的研究与改进基础,用于解决复杂的多目标工程优化问题;③帮助理解非支配排序机制在进化算法中的集成方法及其在实际系统中的仿真实现。; 阅读建议:建议读者结合Matlab代码深入理解算法实现细节,重点关注非支配排序、拥挤度计算和蜣螂行为模拟的结合方式,并可通过替换目标函数或系统参数进行扩展实验,以掌握算法的适应性与参技巧。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值