现在的位置: 首页 > 综合 > 正文

Java虚拟机系列(三)Java内存区域概述

2013年01月30日 ⁄ 综合 ⁄ 共 1735字 ⁄ 字号 评论关闭
文章目录

 

Author:Martin

E-mail:mwdnjupt@sina.com.cn

CSDN Blog:http://blog.csdn.net/ictcamera

Sina MicroBlog ID:ITCamera

Main Reference:

《java深度历险》 王森

《深入理解Java虚拟机-java高级特性与最佳实践》 周志明

1.        Java内存区域一览

1.1.        Java各个内存区域

 

Java虚拟机运行时区域图

区域名称

主要功能

公有/私有

异常情况和扩展参数

其他

程序计数器

字节码行号指示器,类似与程序指针(指令地址)。每个线程都有一个独立的程序计数器,各个线程之间的计数器互不影响,独立存储。

线程私有

如果执行native方法的时候,这个计数器值为空(Undefined

Java虚拟机栈

每个方法执行的时候创建一个栈帧,存储局部变量表、操作栈、动态链接、方法出口等信息,每个方法调用过程就是入栈/出栈过程。其中局部变量表存放了基本的数据类型、对象的引用类型、returnAddress(指向下一条字节指令的地址)

线程私有

线程请求的栈深度大于虚拟机允许的深度时会抛出StackOverflowError。如果虚拟机栈允许动态扩展,当扩展无法申请到足够的内存时会抛出OutOfMemoryError-Xss设置Java虚拟机栈

我们通常所说的虚拟机栈就只指这里的虚拟机栈或者局部变量表。局部变量表所需内存空间在编译期间完成分配,一个方法在帧中的分配多大的局部变量大小是固定的,方法运行期间不改变大小

本地方法栈

Java虚拟机栈作用类似,但是本地方法栈是为执行本地方法来服务的(不是字节码,而是二进制代码)

线程私有

也会抛出异常:StackOverflowErro/OutOfMemoryError-Xoss设置本地方法栈大小

有些虚拟机(例如Sun HotSpotJava虚拟机栈和本地方法栈合一。Sun
HotSpot
通过-Xoss设置本地方法栈大小无效

Java

Java虚拟机管理的最大内存,存在对象实例(包括数组),这块内存物理上不连续,逻辑上连续

线程共享

如果堆中没有足够内存来分配给实例,并且无法扩展,那么会抛出OutOfMemoryError-Xms设置堆的最小值-Xmx设置堆最大值,如果最大值和最小值一样,则堆不可扩展。

 

方法区

存储类信息(版本、字段、方法、接口描述等)、常量静态变量、即时编译后的代码、常量池等

线程共享

方法区无法满足内存分配时抛出OutOfMemoryError-XX:PermSize设置初始值,-XX:MaxPermSize设置最大值。

对这个区域一般很少进行垃圾回收,主要是针对常量池和类型信息的卸载

方法区的运行时常量池

存放编译期生成的各种字面量和符号引用,这部分是类加载后存放到方法区的,当然运行过程中也可能将新的常量放入常量池中如String类的intern()方法。

线程共享

常量池也会受到限制,当常量池无法申请到内存的时抛出OutOfMemoryError。需要通过方法区大小设置参数来改变

 

直接内存

不是Java虚拟机的一部分,可以理解为一个内存缓存。直接内存分配不会受到Java堆大小的限制,但是收到机器物理内存大小的限制

 

一般不会设置这个区域的大小,如果各个区域总和大于物理内存,导致扩展的时候会抛出OutOfMemoryError。通过-XX:MaxDirectMemorySize设置,默认和Java堆的最大值一样。

 

1.2.        与C、C++对应关系

    栈—————————————栈区

    堆—————————————堆区

    方法区(包括常量池)————代码区、常量区

2.        Java对象访问

2.1.        句柄访问对象

 

2.2.        直接指针访问对象

 

2.3.        两种访问方法比较

    句柄方式最大好处就是在引用中存储的是稳定的句柄地址,对象被移动(Java垃圾回收的时候对象经常需要移动)时不需要改变引用,只需要改变句柄的指针。直接指针的方式最大好处就是减少了一层,访问速度更快,由于对象访问速度在Java中非常频繁,因此这个因素对开销影响是非常大的

抱歉!评论已关闭.