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

最新文章

  1. 报文格式:xml 、定长报文、变长报文
  2. Zabbix监控php-fpm status
  3. 瀑布流布局——jquery
  4. win环境安装python爬虫框架scrapy
  5. thinkphp关联模型的用法
  6. Android日志服务 记录日志
  7. delphi 选中的展开0级 子级不展开
  8. Win32 DLL和MFC DLL 中封装对话框
  9. Aho_Corasick自动机(AC自动机)
  10. spark1.3的部署
  11. 杭电ACM1408——盐水的故事
  12. servlet中路径的获取
  13. JQ鼠标右键点击功能 兼容IE8
  14. zookeeper的安装与部署-集群
  15. 数据库用户映射到SQL Server登录名
  16. Java+Selenium自动化对非输入框的日历或日期控件的处理
  17. python 基础———— 字符串常用的调用 (图)
  18. Rest风格理解
  19. psql常用命令
  20. oracle第二天笔记

热门文章

  1. python四种简单排序
  2. windows10安装tensorflow CPU版本
  3. WPF DataTemplate與ControlTemplate
  4. 安卓加固之so文件加固
  5. 【OpenCV】邻域滤波:方框、高斯、中值、双边滤波
  6. “PPT中如何插入和提取swf文件”的解决方案
  7. 记DateTime.Now.ToString()遇到的一个坑
  8. Jquery Easy UI初步学习(一)
  9. [javaSE] GUI(鼠标事件)
  10. 九、sparkStream的scala示例