虽然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. 在Android中调用KSOAP2库访问webservice服务出现的服务端传入参数为null的问题解决

    ksoap2-android-3.0.0-jar 第三方库来调用.net 写的Web Service 如果没有参数,那么调用一切顺利,但是如果服务是带参数的,那么服务端接收的参数都是nul.      ...

  2. Flex 生成行号

    private function formatIndexNumber(item:Object, colum:Object):String {      return indexNumLabelFun( ...

  3. [转]asp.net权限认证:HTTP基本认证(http basic)

    本文转自:http://www.cnblogs.com/lanxiaoke/p/6353955.html HTTP基本认证示意图 HTTP基本认证,即http basic认证. 客户端向服务端发送一个 ...

  4. 为什么会出现__pycache__文件夹?

    为什么会出现__pycache__文件夹? python解释器会将 *.py 脚本文件进行编译,并将编译结果保存到__pycache__目录中. 下次再执行工程时,若解释器发现这个 *.py 脚本没有 ...

  5. Eclipse常用快捷键之技巧篇

    如何让你阅读代码如虎添翼?使用快捷键可以让你快到飞起来~ 显示类的方法和属性:ctrl+o ctrl+o能够看到你的类的层次结构,使你搜索该类某个方法更加的方便 显示类的继承:ctrl+T ctrl+ ...

  6. nodejs记录1——async函数

    其实手动配置babel环境并不难,记录下步骤: 1.首先npm init创建一个nodejs项目 2.全局安装babel-cli处理工具:npm i babel-cli -g 3.cd到项目下安装ba ...

  7. [javaSE] IO流(管道流)

    之前我们使用io流,都是需要一个中间数组,管道流可以直接输入流对接输出流,一般和多线程配合使用,当读取流中没数据时会阻塞当前的线程,对其他线程没有影响 定义一个类Read实现Runable接口,实现r ...

  8. 阿里云服务器windows server流量不大的情况下,tomcat经常出现访问阻塞,手动ctrl+c或者点击右键又访问正常

    我被这个问题折磨了好几天,因为这两天要帮别人做推广,不能再出现这样的情况了,不然广告费就白烧了,所以特意查了一下资料,结果解决方案被我找出来了. 问题发生原因是因为打开编辑选项后,一不小心点到dos窗 ...

  9. UVA1584(环状序列)

    对于序列的最小值,可以定义一个比较的方法,然后用一般找最小值的方法遍历一遍即可 #include <iostream> #include <string> #include & ...

  10. Struts2 (四) — 拦截器

    一.拦截器 1.概述 1.1什么是拦截器 ​ 在struts2中,拦截器(Interceptor)是用来动态拦截Action执行的对象. ​ 拦截器有点类似以前Servlet阶段的Filter(过滤器 ...