zoukankan      html  css  js  c++  java
  • --Too small initial heap for new size specified

    虽然Java屏蔽了一下内存细节,但是有时候,了解一下这些常识还是有好处的,特别是一些面试,总是盯着这些玩意不放手。

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

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

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

    Java代码 复制代码 收藏代码
    1. Error occurred during initialization of VM  
    2. Too small initial heap for new size specified  
      Error occurred during initialization of VM
      Too small initial heap for new size specified

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

    Java代码 复制代码 收藏代码
    1. Exception in thread "main" java.lang.OutOfMemoryError: Java heap space  
    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

     代码为:

    Java代码 复制代码 收藏代码
    1. byte[] b = new byte[100000000];  
    byte[] b = new byte[100000000];

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

    Java代码 复制代码 收藏代码
    1. Exception in thread "main" java.lang.StackOverflowError  
    Exception in thread "main" java.lang.StackOverflowError

     原因一般是:

    Java代码 复制代码 收藏代码
    1. public static int callMyself(){  
    2.     return callMyself();  
    3. }  
    	public static int callMyself(){
    		return callMyself();
    	}

     方法的递归或者死循环,导致栈空间不够用了。

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

    Java代码 复制代码 收藏代码
    1. e.printStackTrace();  
    e.printStackTrace();

     栈信息得知。

    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()可 能会有些大。

    下面我们来看看例子:

    Java代码 复制代码 收藏代码
    1. Runtime rt = Runtime.getRuntime();  
    2.   
    3. info("Max   memory: " + rt.maxMemory());  
    4. long fisrt = rt.freeMemory();  
    5. info("Total memory: " + rt.totalMemory());  
    6. info("Free memory: " + fisrt);  
    7.   
    8. int size = 10000;  
    9.   
    10. byte[] b = new byte[size];  
    11. long bL = rt.freeMemory();  
    12. info("Free memory: " + bL);  
    13.    info("byte allocate Cost memory: " + (fisrt - bL) + ", Array size :" + size);  
    		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 (太大了可能看不出来),运行结果为:

    Java代码 复制代码 收藏代码
    1. 2011-02-22 10:28:01: Max   memory: 33357824  
    2. 2011-02-22 10:28:01: Total memory: 8323072  
    3. 2011-02-22 10:28:01: Free memory: 7791752  
    4. 2011-02-22 10:28:01: Free memory: 7781736  
    5. 2011-02-22 10:28:01: byte allocate Cost memory: 10016, Array size :10000  
    2011-02-22 10:28:01: Max   memory: 33357824
    2011-02-22 10:28:01: Total memory: 8323072
    2011-02-22 10:28:01: Free memory: 7791752
    2011-02-22 10:28:01: Free memory: 7781736
    2011-02-22 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字节):

    Java代码 复制代码 收藏代码
    1. 2011-02-22 10:35:21: int allocate Cost memory: 40016, Array size :10000  
    2011-02-22 10:35:21: int allocate Cost memory: 40016, Array size :10000

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

    将byte换成long(8字节):

    Java代码 复制代码 收藏代码
    1. 2011-02-22 10:32:47: long allocate Cost memory: 80016, Array size :10000  
    2011-02-22 10:32:47: long allocate Cost memory: 80016, Array size :10000

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

    再看看String数组:

    Java代码 复制代码 收藏代码
    1. 2011-02-22 10:34:40: String allocate Cost memory: 40016, Array size :10000  
    2011-02-22 10:34:40: String allocate Cost memory: 40016, Array size :10000

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

    最后看看Object对象,

    Java代码 复制代码 收藏代码
    1. 2011-02-22 10:37:02: Object allocate Cost memory: 40016, Array size :10000  
    2011-02-22 10:37:02: Object allocate Cost memory: 40016, Array size :10000

     与String一样。

    2,第二类内存,我了解的主要是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根本没办法回收

  • 相关阅读:
    vue中局部过滤器的使用
    elementui中switch开关的回调的使用
    css居中的一些方法
    elementui默认样式修改的几种方法
    git查看远程分支,并且切换到远程的分支
    elementui form resetFields方法 无法重置表单
    vue组件使用vuex中的方法报错,报unknown mutation type的错误
    offSet和client和scroll
    842. Split Array into Fibonacci Sequence能否把数列返回成斐波那契数列
    662. Maximum Width of Binary Tree二叉树的最大宽度
  • 原文地址:https://www.cnblogs.com/firstdream/p/8631100.html
Copyright © 2011-2022 走看看