博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
--Too small initial heap for new size specified
阅读量:5910 次
发布时间:2019-06-19

本文共 4666 字,大约阅读时间需要 15 分钟。

虽然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: 333578242011-02-22 10:28:01: Total memory: 83230722011-02-22 10:28:01: Free memory: 77917522011-02-22 10:28:01: Free memory: 77817362011-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根本没办法回收

转载地址:http://juvpx.baihongyu.com/

你可能感兴趣的文章
纹理,这次没用Shader头文件,但是没有报“超出内存”的错误,不知道为什么...
查看>>
idea 去掉never used 提示
查看>>
volatile 关键字的使用
查看>>
学术诚信与职业道德
查看>>
Pascal's Triangle II
查看>>
Palindrome Partitioning
查看>>
2014中国互联网安全大会(ISC)开幕,沃通与您共襄安全盛会
查看>>
Android 修改 keystore 信息
查看>>
jsonp实现下拉搜索
查看>>
对课程学习的期待
查看>>
Tasklist使用详解
查看>>
UVA 1615 Highway
查看>>
Git理解笔记2
查看>>
HashMap原理
查看>>
一年多了,该回来了……
查看>>
四则运算
查看>>
Qt5 for Android: incompatible ABI
查看>>
zookeeper学习
查看>>
Sharepoint contant class
查看>>
class类名的管理
查看>>