• java内存设置


    最近进入天猫物流做运营支撑,需要在不同系统之间切换来切换去。由于各个系统的规模不一,所以遇到了一下在eclipse里调整VM启动参数的问题,拿出来分享下。

    JVM启动以后,会分配两类内存区域,一类用于开发人员使用,比如保存一些变量,对象等,一类JVM自己使用,比如存放一些class类和描述。

    一、第一类内存区域又可以分为栈(stack)、堆(heap),还有一些静态存储区域,这部分的内存在JVM启动的时候,可以用参数进行配置:

    1、-Xms 初始堆大小,这个值不能太小,其初始空间(即-Xms)是物理内存的1/64,这个值不能太小,比如 设置了-Xms1m,运行可能会出现:

    Error occurred during initialization of VM  
    Too small initial heap for new size specified 

    2、-Xmx 堆大小上限,最大空间(-Xmx)是物理内存的1/4,如果程序中分配的内存超过了这个限制,那么会出现:

    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

    可以用代码测试下,譬如:

    byte[] b = new byte[100000000]; 

    3、-Xss  线程栈大小,一般不用设置,JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。有时候会发现一下异常:

    Exception in thread "main" java.lang.StackOverflowError

    原因一般是方法的递归或者死循环,导致栈空间不够用了,譬如:

    public static int callMyself(){  
        return callMyself();  
    }  

    4、栈和堆到底存些什么,很多地方都有讲到,这里参考下《Think in java》的,栈里存放对象引用、基本类型的变量等,而堆里面存放对象和数组。方法的执行是在栈上进行的,这一点可以通过异常的时候,经常会默认打印栈信息得到:

    e.printStackTrace();

    5、Runtime类有几个函数,我们可以简单的通过这几个函数,看看JVM中的一些内存信息。


    maxMemory()这个方法返回的是java虚拟机(这个进程)能构从操作系统那里挖到的最大的内存,以字节为单位,如果在运行java程序的时 候,没有添加-Xmx参数,那么就是64兆,也就是说maxMemory()返回的大约是64*1024*1024字节,这是java虚拟机默认情况下能 从操作系统那里挖到的最大的内存。如果添加了-Xmx参数,将以这个参数后面的值为准,例如java -cp ClassPath -Xmx512m ClassName,那么最大内存就是512*1024*0124字节。

    totalMemory()这个方法返回的是java虚拟机现在已经从操作系统那里挖过来的内存大小,也就是java虚拟机这个进程当时所占用的所有 内存。如果在运行java的时候没有添加-Xms参数,那么,在java程序运行的过程的,内存总是慢慢的从操作系统那里挖的,基本上是用多少挖多少,直 挖到maxMemory()为止,所以totalMemory()是慢慢增大的。如果用了-Xms参数,程序在启动的时候就会无条件的从操作系统中挖- Xms后面定义的内存数,然后在这些内存用的差不多的时候,再去挖。

    freeMemory()是什么呢,刚才讲到如果在运行java的时候没有添加-Xms参数,那么,在java程序运行的过程的,内存总是慢慢的从操 作系统那里挖的,基本上是用多少挖多少,但是java虚拟机100%的情况下是会稍微多挖一点的,这些挖过来而又没有用上的内存,实际上就是 freeMemory(),所以freeMemory()的值一般情况下都是很小的,但是如果你在运行java程序的时候使用了-Xms,这个时候因为程 序在启动的时候就会无条件的从操作系统中挖-Xms后面定义的内存数,这个时候,挖过来的内存可能大部分没用上,所以这个时候freeMemory()可 能会有些大。

    譬如:

    Runtime rt = Runtime.getRuntime();  
      
    info("Max   memory: " + rt.maxMemory());  
    long fisrt = rt.freeMemory();  
    info("Total memory: " + rt.totalMemory());  
    info("Free memory: " + fisrt);  
      
    int size = 10000;  
      
    byte[] b = new byte[size];  
    long bL = rt.freeMemory();  
    info("Free memory: " + bL);  
       info("byte allocate Cost memory: " + (fisrt - bL) + ", Array size :" + size); 

    运行参数设置为 -Xms8m -Xmx32m (太大了可能看不出来),运行结果为:

    2013-12-26 10:28:01: Max   memory: 33357824  
    2013-12-26 10:28:01: Total memory: 8323072  
    2013-12-26 10:28:01: Free memory: 7791752  
    2013-12-26 10:28:01: Free memory: 7781736  
    2013-12-26 10:28:01: byte allocate Cost memory: 10016, Array size :10000

    33357824 <> 32*1025*1024(大约等于)
    8323072 <> 8×1024×1024
    最后看看10000长度的byte数组,分配了多少内存,大约为10016,这说明除了10000个大小为1字节的byte以外,还有16个字节其他的玩意。

    将byte换成int(4字节):

    2013-12-26 10:35:21: int allocate Cost memory: 40016, Array size :10000

    与byte相同,也是4*10000+16

    将byte换成long(8字节):

    201312-26 10:32:47: long allocate Cost memory: 80016, Array size :10000

    与byte相同,也是8*10000+16

    再看看String数组:

    2013-12-26 10:34:40: String allocate Cost memory: 40016, Array size :10000

    String作为一个对象,分配的内存大小与int相同,说明了这台机器是32(4*8)位的

    最后看看Object对象:

    2013-12-26 10:37:02: Object allocate Cost memory: 40016, Array size :10000

    结果与String一样。

    二、第二类内存,我了解的主要是PermGen space,全称是Permanent Generation space,是指内存的永久保存区域,这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中,它和存放类实例(Instance)的Heap区域不同,SUN的JDK在GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的应用中有很CLASS的话,就很可能出现PermGen space错误。原来SUN 的JVM把内存分了不同的区,其中一个就是permenter区用来存放用得非常多的类和类描述。本来SUN设计的时候认为这个区域在JVM启动的时候就 固定了,但他没有想到现在动态会用得这么广泛。而且这个区域有特殊的垃圾收回机制,现在的问题是动态加载类到这个区域后,gc根本没办法回收!这个后续再讨论。

  • 相关阅读:
    SQl 事务 异常和游标
    SHarepoint 2007 内容类型
    如何在Sharepoint 2010 中使用Session
    Jquery 选择器
    学习资料
    创建自定义主机头网站集
    MOSS Single Sign On Setup StepByStep
    toolip 属性小知识
    基于多层结构的网络游戏平台的研究与应用
    Jabber 技 术 概 况
  • 原文地址:https://www.cnblogs.com/zengdan-develpoer/p/3491995.html
Copyright © 2020-2023  润新知