前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JVM内存分配参数对程序性能的影响

JVM内存分配参数对程序性能的影响

作者头像
Java深度编程
发布2022-03-17 15:26:02
9350
发布2022-03-17 15:26:02
举报
文章被收录于专栏:Java深度编程Java深度编程

文章首发在https://www.amoshuang.com/archives/1901 使用IDEA的小伙伴可以在Run -> Edit Configurations 设置VM options属性来设置JVM参数。 1. 设置最大堆 使用-Xmx参数可以指定Java应用程序的最大堆。最大堆为新生代和老年代的大小纸盒的最大值,是Java程序的堆上限。 使用如下代码进行测试,每次循环将会向容器v中增加1M的数据。

代码语言:javascript
复制
public class TestXmx {
  public static void main(String args[]){
      Vector v=new Vector();
      for(int i=1;i<=10;i++){
          byte[] b=new byte[1024*1024];
          v.add(b);             //强引用,GC不能释放空间
          System.out.println(i+"M is allocated");
      }
      System.out.println("Max memory:"+Runtime.getRuntime().maxMemory()/1024/1024+"M");
  }
}

当使用参数-Xmx11M进行运行时,程序可以顺利结束并且没有任何异常。但当使用参数-Xmx5M进行运行时,则会报OutOfMemoryError错误。 在运行时,可以使用Runtime.getRuntime().maxMemory()方法获取最大堆内存。

2.设置最小堆内存 使用参数-XMS 可以用于设置系统的最小堆空间,也就是JVM启动时所占据的操作空间大小。 Java应用程序在运行时,首先会分配指定大小的内存大小,并尽可能在这个空间段内运行程序。当-Xms指定的内存大小确实无法满足应用程序时,JVM才会向操作系统申请更多的内存,知道内存大小达到-Xmx指定的大小为止。若超过,则抛出OutOfMemoryError错误。 如果-Xms太小,则会导致JVM为了保证系统尽可能可以在指定内存范围内运行而频繁进行GC操作,以释放失效的内存空间,从而对系统性能产生影响。 注意:将-XmS值设置为-Xmx的值,可以减少在系统运行初期GC的次数和耗时。

3.设置新生代 参数-Xmn可用于设置新生代大小。设置一个较大的新生代会减小老年代的大小,这个参数对系统性能以及GC行为有很大的影响。新生代的大小一般设置为整个堆空间的1/4到1/3左右。 4.设置持久代 持久代(方法区)不属于堆的一部分,在Hot Spot虚拟机中,使用-XX:MaxPermSize可以设置持久代的最大值,使用-XX:PermSize可以设置持久代的初始大小。 持久代的大小直接决定了系统可以支持多少各类定义和多少常量,设置合理的持久代大小有助于维持系统的稳定。 系统支持的最大类数量,与MaxPermSize成正比。一般来说,MaxPermSize设置为64MB已经可以满足绝大部分应用程序正常工作。如果依然出现永久区溢出,可以将MaxPermSize设置为128MB。这是两个常用的永久区取值。如果128MB依然不能满足应用程序需求,那么对于大部分应用程序而言,应该考虑优化系统设计,减少动态类的产生,或者利用GC回收部分驻扎在永久区的无用类信息,以使系统健康运行。 5.设置线程栈 线程栈是线程的一块私有空间,在JVM中,可以使用-Xss参数设置线程栈的大小。 在线程中进行局部变量分配、函数调用时,都需要在栈中开辟空间。如果栈空间分配太小,那么线程在运行时,可能会因为没有足够的空间分配局部变量或者达不到足够的函数调用深度,导致程序异常退出。如果栈空间太大,那么开设线程所需的内存成本就会上升,系统所能支持的线程总数就会下降。 因为Java堆也是向操作系统申请内存空间,因此如果堆空间太大,就会导致操作系统可用于线程栈的空间减少,从而间接减少程序所能支持的线程数量。 以下代码会尝试尽可能的开设线程,并且在线程数量饱和时,打印已经开设的线程数量:

代码语言:javascript
复制
public static class MyThread extends Thread{
        @Override
        public void run(){
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String args[]){
        int i=0;
        try{
            for( i=0;i<10000;i++){
                new MyThread().start();
            }
        }catch(OutOfMemoryError e){
            System.out.println("count thread is "+i);
            e.printStackTrace();
        }
    }

首先使用-Xss1M运行程序,即设置每个线程拥有1MB的栈空间,在我的计算机上,总共可以开设线程1168个。当使用-Xss10M运行程序时,公共可以137个线程。 如果尝试在JVM参数中指定堆大小,则会发现系统所支持的线程数和对大小还有关系: -Xss1M -Xss20M -Xms100m -Xms100M 1170 66 -Xms300m -Xms300M 1139 64 -Xms500m -Xms500M 998 55 -Xms700m -Xms700M 852 44 当系统空间不够而无法创建新的线程时,会抛出OutOfMemoryError错误。但这并不是因为堆内存不够而造成的OOM,在这种情况下,应该尝试减少堆内存,以换取更多的系统空间来解决这个问题。 综上,如果系统确实需要大量线程并发执行,那么设置一个较小的堆和较小的栈有助于提高系统所能承受的最大线程数。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-02-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java深度编程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档