`
zk_chs
  • 浏览: 212873 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

Java中的内存区域

    博客分类:
  • JVM
 
阅读更多

写这篇博客是为了自己能够再次复习一下JVM,《深入理解java虚拟机》这本书算我的是启蒙教科书了,

这次重读是要把以前模糊的、忘记的部分记录下来。

 

首先说清楚,内存区域不是内存模型,指的是大家常说的栈、堆、方法区(JDK8中已经改为Metaspace)

 

虚拟机栈:

每一条线程有一个属于自己的虚拟机栈,而在这条线程执行时,会创建一个个的栈帧,栈帧就是一个个方法,

这么一来,栈帧内部存储的内容也就简单明了了,栈帧内存储局部变量表、操作数栈、方法出口等信息。

 

每一个方法的开始与结束,便对应一次入栈与出栈的过程,(栈是一种后进先出的数据结构)

 

栈帧中最重要的应该就是局部变量表了,局部变量表内存储有8中基本类型与对象引用地址,

注意:这里不是存储对象,对象存在堆内存中!这里是仅存储引用地址

 

-Xss:可以设置每一个虚拟机栈的大小,如-Xss256k

 

无论是栈帧太大还是虚拟机栈容量太小,当内存无法分配时,都会抛出StackOverflowError的异常

比如说使用了递归方法调用而无法终止时,便会抛出上述异常

 

Java堆:

为最大的一块内存,所有线程共享,用于分配存放对象实例

 

堆又可以分为新生代和老年代;

新生代又划分为3个区域:Eden、From Survivor、To Survivor

 

关于上面细分出来的4个区域,都可以通过jvm启动参数进行设置:

-Xmx:堆最大大小,如-Xmx512m

-Xms:堆初始大小,-Xms256m

 

设置新生代与老年代的两种方法:

-Xmn:新生代大小,通常为-Xmx的1/3或1/4-XX:NewRatio:新生代与老年代的比例,-XX:NewRatio=2,代表新生代占总堆的1/3,老年代2/3

 

设置新生代中区域大小:

-XX:SurvivorRatio:新生代中Eden与任一Survivor的比例,-XX:SurvivorRatio=8为默认值,代表Eden占新生代的8/10

 

当为对象分配内存,而GC(垃圾回收)又无法清理出内存的情况下,会发生Heap Space OutOfMemory Error

使用参数-XX:+HeapDumpOnOutOfMemoryError,-XX:HeapDumpPath=/xxx/xxx/xxx.hprof

可以在Heap OutOfMemory 的时候产生转储快照,然后进行分析,第二个参数可以指定dump文件位置

 

方法区:

所有线程共享,用于存储被虚拟机加载的类信息、常量、静态变量等数据,方法区也被称为永久代

但是被称为永久代缺不代表这部分内存不会被回收

 

-XX:PermSize:方法区的初始值,-XX:PermSize=64m

-XX:MaxPermSize:方法区的最大值,-XX:MaxPermSize=128m

 

方法区主要存放Class的相关信息,当运行时加载太多的类便会发生OutOfMemoryError: PermGen space

 

直接内存:

还有一种内存为直接内存,不属于虚拟机运行时数据区的一部分。

比如NI/O,可以通过Native方法直接分配内存,受到本机总内存的限制

 

 可以通过-XX:MaxDirectMemorySize来指定大小,默认与-Xmx相同

Java中申请分配内存的方法为unsafe.allocateMemort()方法,unsafe为Unsafe的一个实例

Unsafe这个类并没有对我们开放,需要反射获取实例

 

内存溢出时抛出OutOfMemoryError,at sun.misc.Unsafe.allocateMemory(Native Method)

 

 

 

上述的内容也许不够详尽,不过由于个人表达能力欠缺,也只能写这么多了;

相信每个人都有自己独特的理解,以上可以作为参考来学习

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics