深入理解java虚拟机

来源:互联网 发布:大数据技术体系图 编辑:程序博客网 时间:2024/05/20 09:05

我们可以把java程序设计语言、java虚拟机、java API类库称为JDK

把JAVA API类库中的JAVA SE API 子集和 java虚拟机 这两部分统称为JRE

多核并行,JDK1.5引入java.util.concurrent 包 实现一个粗粒度的并发框架

JDK 1.7 java.util.concurrent.forkjoin包

开源JDK openJDK

编译jdk

2、自动内存管理机制

程序计数器是一块较小内存空间类,当前线程所执行的字节码的行号执行器

java虚拟机栈,线程私有,生命周期与线程一样,描述的是java方法执行的内存模型,每个方法被执行的时候同时会创建一个栈帧

用于存储局部变量表,操作栈,动态链接、方法出口

局部变量表存放了基本数据类型、对象引用类型

64位长度的long和double类型数据会占用2个局部变量空间,其他类型只占用一个

方法运行期间不会改变局部变量表的大小

如果线程请求的栈深度大于虚拟机所允许的深度,将抛出stackoverflowerror异常,

当扩展时无法申请到足够的内存时会抛出outofmemoryerror异常


本地方法栈与虚拟机栈作用类似

java堆是被所有线程共享的一块内存区域,如果堆中没有内存完成实例分配,并且堆也无法扩展时,将会抛出outofmemoryerror

方法区 是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、

HotSpot 永久代

运行时常量池

运行期间也可能将新的常量放入池中,String类的intern方法,也可能会抛出outofmemoryerror

直接内存 不会受到java堆大小的限制,会受本机总内存的大小以及处理器寻址空间的限制,配置虚拟机参数 设置-Xmx等参数信息

由于reference类型在java虚拟机规范里只规定一个指向对象的引用


不同虚拟机实现访问对象的方式不同,主流的有使用句柄和直接指针

1、使用句柄访问方式的话,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址

      句柄池和实例池在java堆里面

2、 使用直接指针访问方式,java堆对象的布局就必须考虑如何放置访问类型数据的相关信息,reference中直接存储的就是对象地址


java堆 

-不可扩展,将堆最小值-Xms和最大值-Xmx设置一样即可避免堆自动扩展

-堆转存快照,通过参数-XX:+HeapDumpOnOutOfMemoryError

-VM arguments :    -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8

-出现堆内存溢出时,会提示java heap space,要解决这个区域的异常,一般手段是通过内存映像分析工具,如eclipse memory analyzer对dump出来的

堆转储快照进行分析,重点是确认内存中的对象是否有必要,要分清楚是出现了内存泄漏还是内存溢出

-处理思路:如果是内存泄漏,可以进一步通过工具查看泄漏对象到GC Roots的引用链,于是就能找到泄漏对象是通过怎么样的路径与GC Roots相关联并导致

垃圾收集器无法自动回收它们的,掌握了泄漏对象的类型信息,以及GC Roots引用链的信息,就可以比较准确的定位出泄漏代码的位置了,

如果不存在泄漏,内存中的对象确实都还必须存活着,那就应当检查虚拟机的堆参数-Xmx与-Xms,与机器物理内存对比是否还可以调大,

从代码上检查是否存在某些对象生命周期过长,持有状态时间过长的情况,尝试减少程序运行期的内存消耗。