JVM内存浅谈

3/8/2017来源:ASP.NET技巧人气:2047

网上有太多关于java堆,栈的文章,但表述都各不一,有些甚至误导人。今天,我想自己了解到的,比较正确的来聊一下JVM的内存。

遵照JVM规范,内存大致可划分为方法区、堆、本地方法栈、PC寄存器和栈。

        

方法区

方法区存放了要加载类的信息、域的信息、方法信息、静态变量(类变量)、final类型的常量。(有关静态与常 量自行去了解)

    方法区是全局共享的,在一定条件下也会被GC,当使用的内存超过其允许的大小时,会抛出OutOfMemory。

这块区域对应持久代,默认最小16MB,最大64MB,可通过-XX:PermSize及-XX:MaxPermSize来修改。

常量池属于方法区,顾名思义,就是用来存放常量的,JVM会给每个类型维护一个常量池。

堆用于储存对象实例及数组,可以认为所有通过new创建的对象内存都在此分配。堆中对象所占的内存GC

进行回收。内存大小可通过-Xms(最小内存),-Xmx(最大内存)来修改。堆可分为新生代和旧生代。新生

代又由Eden Space和两块相同大小的Survivor Space构成。堆是全局共享的,JVMnew创建的实例对象,

对象的引用内存分配在栈中,对象分配在堆中,而实例对象中的成员变量,不管是基本类型的,还是实例

变量,都存放在堆中(包括引用)。(网上有很多文章对此有误导)

本地方法栈

本地方法栈用于支持native方法的执行。存储了每个native方法调用的状态。

PC寄存器和栈

每个线程都有自己的PC寄存器和栈。PC寄存器占用的可能为CPU寄存器或者操作系统的内存,栈占用的是

操作系统内存。栈为线程私有。方法中局部变量,如果为基本类型,则变量与值存放在栈中,如果为引用

变量时,则栈中存放引用(对象的内存地址),对象存放在堆中。当方法运行完毕时,其对应的栈帧所占

用的内存会自动释放。

当栈空间不足时,会抛出StackOverflowError。可通过-Xss来修改。