好久没有整理这方面的东西了。现在整理一下JVM相关的东西。这是第一篇,JVM内存模型。
进程&JVM
首先,何谓JVM?为什么要有JVM的存在?
JVM就是java virtual machine的简称。当然了,除了java的VM以外还会有好多别的虚拟机。java的VM模型有好几个,其中最常见的应该是HotSpot VM。
假设jvm在一个32位的操作系统中运行。32位windows最大只支持4G内存,而进程只能最多2G内存;32位linux最大也只支持4G内存,但是进程最多可以有3G左右。画个图来更清晰的表示:
jvm首先就是一个程序。一个虚拟机,用于执行java的虚拟机。具体这个虚拟机的大小是可以调整的,但是最大不会超过系统进程的大小。先把内存分为两块:
- 虚拟机内的内存
- direct memory
direct memory有好多的叫法。比如说non-heap memory(与perm有区分),un-safe memory等。在一个进程中,JVM分配的内存越大,direct memory就会越小。使用这一块内存的好处,就一个字,快!因为虚拟机里面的“安全”内存,是经过jvm分配的。而direct memory是直接使用程序的内存。然而!不经过JVM的这一块内存是不会经过垃圾回收管理的。这块内存对于java来说,使用不当是相当有风险的。
用两行代码描述这二者的区别:
ByteBuffer buffer = ByteBuffer.allocateDirect(ONE_MB*128); ByteBuffer buffer = ByteBuffer.allocate(ONE_MB*128);
有兴趣的童鞋自己玩玩,当分配很大的内存时候,上面两行代码都会抛出OOM异常。但是OOM的内容是不同的。
虚拟机内的内存分布
虚拟机是用于运行程序的。而程序本身是通过指令执行,通过变量对象运算。指令归于stack(栈),变量对象归于heap(堆)。其次,还有一个叫做non-heap的内存用于放对象的格式等信息,运行时常量等(与direct memory有区别)。借用stackOverflow里面的一个图展示:
上述3块东西,都是在jvm里面的。3块东西分别用于不同的职能。
分代管理的heap
上图的第三块内存heap。是理解jvm模型中最核心的一个部分。电脑有安装jdk的话,会有一个visualVm的程序。然后安装了visualGC插件,可以很清晰的看到这一块内存的情况。参考(http://www.mamicode.com/info-detail-632507.html)
下面来个图片:
看这个图就一点都不抽象了^_^
这里有一个eden、2个survivor、一个old和perm的区域。首先注意,perm是non-heap的。perm并不算在heap里面。
不算perm,为何要有这么几个区域呢??
创建的对象一开始是在eden区域的。绝大部分对象,其实很快就没有被使用了。那么当eden满了后,stop the world。然后把存活的对象放到一个survivor区域中。等eden区又满了,把eden存活的和上次那个survivor中的对象放到另外一个survivor区域中。(新生代的垃圾回收过程)
假设其中一个survivor区域满了,也依然对象在使用,就把这些对象放到old区中。(基于copying的垃圾回收)
old区满了,就不能再复制了,在自身中标记--整理(基于mark--compact的垃圾回收)
简单的说,这样子划分是根据对象的生命周期和垃圾回收原理来分区域的。更详细的说明,要跟垃圾回收结合了。