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

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

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

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

  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,如果程序中分配的内存超过了这个限制,那么会出现

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

代码为:

  1. byte[] b = new byte[100000000];
byte[] b = new byte[100000000];

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

  1. Exception in thread "main" java.lang.StackOverflowError
Exception in thread "main" java.lang.StackOverflowError

原因一般是:

  1. public static int callMyself(){
  2. return callMyself();
  3. }
	public static int callMyself(){
return callMyself();
}

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

栈和堆到底存些什么,很多地方都有讲到,这里参考下《Think in 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()可 能会有些大。

下面我们来看看例子:

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

  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字节):

  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字节):

  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数组:

  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对象,

  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根本没办法回收

--Too small initial heap for new size specified的更多相关文章

  1. java "Too small initial heap" 错误

    Tomcat内存配置 JAVA_OPTS="-server -Duser.timezone=GMT+08-Xms1024m -Xmx1024m -XX:PermSize=1024m -Xmn ...

  2. Invalid initial heap size: -Xms

    -Xxs512m注意 Xxs 和 512m中间无空格就行了.

  3. JDK分析工具&JVM垃圾回收(转)

    转自:http://blog.163.com/itjin45@126/blog/static/10510751320144201519454/ 官方手册:http://docs.oracle.com/ ...

  4. Java I/O 操作及优化建议

    Java I/O I/O,即 Input/Output(输入/输出) 的简称.就 I/O 而言.概念上有 5 种模型:blocking I/O.nonblocking I/O,I/O multiple ...

  5. tomcat的一些优化及报错

    以下为转发来,具体地址为 http://blog.csdn.net/chen3888015/article/details/7432488 环境centos5.7 tomcat6 http://apr ...

  6. JAVA 内存的那些事

    (转载)固然Java屏蔽了一下内存细节,但是有时候,了解一下这些常识还是有好处的,特别是一些口试,总是盯着这些玩意不放手. JVM启动以后,会分配两类内存区域,一类用于开发职员使用,比如保存一些变量, ...

  7. “Invalid maximum heap size” when running Maven

    运行mvn package,报错: Invalid maximum heap size: -Xmx512m. Error: Could not create the Java Virtual Mach ...

  8. Find out your Java heap memory size

    In this article, we will show you how to use the -XX:+PrintFlagsFinal to find out your heap size det ...

  9. 关于java.lang.OutOfMemoryError: Java heap space的错误分析

    今天无意间遇到这个错误:java.lang.OutOfMemoryError: Java heap space 问题出现原因:使用a标签实现快速下载[当然已经实现了,但想了想还是要归纳解决这类问题] ...

随机推荐

  1. C#多线程学习一

    一.概述:C#支持多线程并行执行程序,一个线程有他单独的执行路径,能够与其他线程同时执行,一个程序是由一个单线程开始,该单线程由CLR(公共语言运行时)和操作系统创建而成,并具有多线程创建额外线程的功 ...

  2. 解析XML:DOM,SAX,PULL

    Android解析XML有三种方式:DOM(document object model).SAX(simple api XML).PULL 1.DOM DOM解析XML文件时,会将XML文件的所有内容 ...

  3. linux进程间的网络通信

    一.进程是如何进行网络通信的?socket通信的过程? 同一机器上的不同进程之间的通信方式有很多种,主要使用消息传递或共享内存.而跨网络的进程是几乎都是使用socket通信,例如web服务器,QQ. ...

  4. jQuery中hover与mouseover和mouseout的区别分析

    本文实例分析了jQuery中hover与mouseover和mouseout的区别.分享给大家供大家参考,具体如下: 以前一直以为在jquery中其实mouseover和mouseout两个事件等于h ...

  5. weblogic.rjvm.PeerGoneException

    并发weblogic异常,报错如下: weblogic.rjvm.PeerGoneException: ; nested exception is: weblogic.utils.net.Socket ...

  6. String.replace与String.format

    字符串的替换函数replace平常使用的频率非常高,format函数通常用来填补占位符.下面简单总结一下这两个函数的用法. 一.String.replace的两种用法 replace的用法如:repl ...

  7. js文件加载太慢,JavaScript文件加载加速

    原文出自:https://blog.csdn.net/seesun2012 js脚本加载太慢,JavaScript脚本加载加速(亲测有效) 测试背景: JS文件大小:6.1kB 传统形式加载js文件: ...

  8. 怎么让一段xml被识别为字符串

    public static String decodeString(String strData) { strData = replaceString(strData, "<" ...

  9. 四、spark集群架构

    spark集群架构官方文档:http://spark.apache.org/docs/latest/cluster-overview.html 集群架构 我们先看这张图 这张图把spark架构拆分成了 ...

  10. Rabbit安装(windows)

    安装rabbit后,启动服务,浏览器打开控制台找不到.查百度说是要装插件.翻了好几篇都是互相抄,没有能用到. 多翻了几篇终于找到一个靠谱的.可以打开控制台了.记录下: 首先要安装Erlang语言支持, ...