Gnod

导航

 
不习惯写成Blog, 主要是觉得图片上传略显麻烦, 另外博客也不是自己搭的没多大成就感也没多大捣腾的动力==~. 突然翻出了这个博客, 似乎很寒碜, 赶紧翻看了下evernote, 发现上个月写得jvm相关比较似乎不用过多整理就能放上来......
 
JVM在执行Java程序时, 将其所管理的内存区域划分为五个部分: 程序计数器, 方法区, 堆, 虚拟机栈, 本地方法栈.
 
1. 程序计数器:
    用于存放下一条执行指令的 字节指令码地址
    由字节解释器读取
    线程私有
 
2.  堆:
     线程共有
     存放对象实例及数组
 
3. 虚拟机栈:
     线程私有
     描述 Java方法执行的内存模型: 每个方法执行时都同时创建一栈帧, 用于存放方法设计的局部变量表, 操作栈, 动态链接, 方法的入口信息等.
     每一个方法从调用到执行完成过程均对应一栈帧在虚拟机栈中的入栈到出栈过程.
 
     局部变量表中存放基本数据类型(boolean, byte, short, int, float, long, double), 对象引用 和 returnAddress类型(指向一条字节码指令的地址) 
     局部变量表中, 除64bit的long与double占用2个局部变量空间(slot) , 其余数据类型均占据1空间, 并且局部变量表所占空间在编译期间即已经确定, 进入方法时, 局部变量表在栈帧中所占据的空间完全确定, 在方法运行期间不会改变.
     
     异常情况:
          当线程申请的栈深 大于 虚拟机所允许的栈深时, 抛出StackOverFlowError
          当虚拟机栈动态无法申请到足够的内存空间时, 抛出OutOfMemoryError
 
4. 本地方法栈:
     本地方法栈跟虚拟机栈基本相同, 但服务对象为Native 方法
 
     有些虚拟机将  虚拟机栈与本地方法栈合并为一个(如Sun Hotspot虚拟机)
 
 
5. 方法区:
     线程共有
     存储已被虚拟机加载的类信息, 常量, 静态变量, 及即时编译器编译后的代码等数据
     (实际上Java虚拟机规范将方法区描述为堆的一个逻辑部分)
 
     运行时常量池  属于方法区中的一部分, 用于存放编译后生成的各种字面量和符号引用.
          运行时常量池具有动态扩展性, 在运行期间可以有将新的常量添加到常量池中, 如String的intern方法
 
 
6. 直接内存
     JDK 中NIO类可以通过Native函数库直接分配堆外内存, 通过堆中的DirectByteBuffer对象引用指向该内存进行操作.
 
 
7. 对象访问:
     JVM中对对象引用定位对象实例的实现方式可以分为两种:
          对象引用指向 代表对象实例的句柄地址. JVM在Java堆中分配一块内存做为句柄池, reference对象指向对应句柄地址, 句柄中包含了对象实例数据地址及对象类型数据地址.
          优点在于对象实例地址发生改变时, 只需改变句柄中的相应地址.
 
          对象引用使用指针方式访问, 直接指向对象实例地址.  
          优点为访问速度快
 
 
8. JVM对各内存块的参数设定:
     Java堆: -Xms 指定最小堆大小(如-Xms20m)
             -Xmx 指定堆的最大值
          当限定-Xms , -Xmx指定大小一致时可避免堆的动态扩展
 
     Java栈: -Xss  
             -Xoss 该参数仅当JVM实现上将虚拟机栈及本地方法栈分开时用于设定本地方法栈的大小
 
     Java方法区:
          -XX:PermSize     
          -XX:MaxPermSize
 
     直接内存:
          -XX:MaxDirectMemorySize
posted on 2013-01-05 14:08  Gnod  阅读(209)  评论(0)    收藏  举报