JVM 学习笔记(一)
2014-05-05 18:45
169 查看
JVM ----Java Virtual Machine (熟称:JAVA虚拟机),JVM 在执行JAVA程序的过程中将内容划分为若干个区域,其有各自的用途和管理机制。如下图:
1. 程序计算器(Program Counter Register) -- 是当前线程所执行字节码的行号指示器,通过改变其值来实现执行不同的代码指令。内存占用小,线程私有,支持多线程处理(多线程时,每个线程有一个独立程序计算器,已达到各自互不影响), 也正是由于这些特点,该区域是JVM规范中唯一没有规定任何OutOfMemoryError的区域。
2. JAVA 虚拟机栈(JVM Stack)
也是线程私有,和线程有相同的生命周期,是JAVA方法执行的内存模型, 即:每个方法执行时,都会同时创建一个Stack Frame(栈帧)用于存储局部变量(8种基本数据类型、对象引用类型)、操作数栈、动态链接、方法出口信息。方法调用到执行完成的过程也是Stack Frame栈帧出、入JVM Stack的过程.
在JVM规范中,规定了两种内存异常:
一是:线程请求的栈深度超过了栈允许的最大深度,将抛出:StackOverflowError 异常。
二是:当JAVA虚拟机动态扩展时,无法申请到足够的内存时,将抛出:OutOfMemoryError异常。
以下样例属于第一种情形:
运行结果:
Stack length:7907
Exception in thread "main" java.lang.StackOverflowError
at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java 13)
at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java 13)
at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java 13)
... (省略相同栈信息)
以下属于第二种情形:(注意!!!: 在运行以下样例前,请保持所有工作,可能导致操作系统假死。)
运行结果为:
Exception in thread "main" java.lang.OutofMemoryError: unable to create new native thread.
3. 本地方法栈(Native Method Stack)
与JVM stack 相似,JVM stack 为虚拟机执行JAVA方法服务,而Native Method Stack 是为虚拟机执行本地方法服务。有的虚拟机对两者没有区分,合二为一。
同样会存在两种异常: StackOverflowError 和 OutOfMemoryError 异常. (样例如第2点中)
4. JAVA 堆(Heap)
Heap 是java内存管理中最大的一块内存区域,被所有线程共享,用于存放对象实例,几乎所有的对象实例和数组都在此分配。
在JVM规范中规定,JAVA堆可以物理不联系,只要逻辑空间联系即可。这样,当堆Heap无法完成再扩展时,将会抛出:OutOfMemoryError异常。
所以,不断的创建对象,就会导致内存溢出.
运行结果为:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Unknown Source)
at java.util.Arrays.copyOf(Unknown Source)
at java.util.ArrayList.grow(Unknown Source)
at java.util.ArrayList.ensureExplicitCapacity(Unknown Source)
at java.util.ArrayList.ensureCapacityInternal(Unknown Source)
at java.util.ArrayList.add(Unknown Source)
at HeapOOM.main(HeapOOM.java:17)
5. 方法区(Method Area)
方法区也是多线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译的代码数据。(JVM规范把方法区描述为堆的一个逻辑区域)
方法区在无法满足内存分配时,将抛出OutOfMemoryError 异常。
6. 运行时常量池(Runtime Constant Pool )
运行时常量池是方法区的一部分,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池。
运行结果:
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
at java.lang.String.intern(Native Method)
at RuntimeConstantPoolOOM.main(RuntimeConstantPoolOOM.java 13)
....
7. 直接内存(Direct Memory)
本机内存分配不受JAVA 虚拟机(堆,栈等)的影响,但是受机器内存的影响,当各区域内存总和大于物理内存时,导致动态扩展内存出现:OutOfMemoryError异常。
[b]对象访问[/b]
对象访问主要有两种方式:
一种是,通过句柄访问对象;(优点在于:reference 中存储的是稳定的句柄地址,在对象被移动时,只改变句柄中实例数据指针,而reference本身不变)
一种是,通过直接指针访问对象。(优点在于:速度更快,节省了一次指针定位时间)
1. 程序计算器(Program Counter Register) -- 是当前线程所执行字节码的行号指示器,通过改变其值来实现执行不同的代码指令。内存占用小,线程私有,支持多线程处理(多线程时,每个线程有一个独立程序计算器,已达到各自互不影响), 也正是由于这些特点,该区域是JVM规范中唯一没有规定任何OutOfMemoryError的区域。
2. JAVA 虚拟机栈(JVM Stack)
也是线程私有,和线程有相同的生命周期,是JAVA方法执行的内存模型, 即:每个方法执行时,都会同时创建一个Stack Frame(栈帧)用于存储局部变量(8种基本数据类型、对象引用类型)、操作数栈、动态链接、方法出口信息。方法调用到执行完成的过程也是Stack Frame栈帧出、入JVM Stack的过程.
在JVM规范中,规定了两种内存异常:
一是:线程请求的栈深度超过了栈允许的最大深度,将抛出:StackOverflowError 异常。
二是:当JAVA虚拟机动态扩展时,无法申请到足够的内存时,将抛出:OutOfMemoryError异常。
以下样例属于第一种情形:
/** * VM Args: -Xss128K * @author yql * */ public class JavaVMStackSOF { private int stackLength = 1; public void stackLeak(){ stackLength ++; stackLeak(); } public static void main(String[] arg) throws Throwable{ JavaVMStackSOF oom = new JavaVMStackSOF(); try{ oom.stackLeak(); }catch(Throwable e ){ System.out.println("Stack length:"+ oom.stackLength); throw e; } } }
运行结果:
Stack length:7907
Exception in thread "main" java.lang.StackOverflowError
at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java 13)
at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java 13)
at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java 13)
... (省略相同栈信息)
以下属于第二种情形:(注意!!!: 在运行以下样例前,请保持所有工作,可能导致操作系统假死。)
/** * VM Args: -Xss2M * @author yql * */ import java.lang.*; public class JavaVMStackOOM { private void dontStop(){ while(true){ } } public void stackLeakByThread(){ while(true){ Thread thread = new Thread(new Runnable(){ @Override public void run(){ dontStop(); } }); thread.start(); } } public static void main(String[] arg) throws Throwable{ JavaVMStackOOM oom = new JavaVMStackOOM(); oom.stackLeakByThread(); } }
运行结果为:
Exception in thread "main" java.lang.OutofMemoryError: unable to create new native thread.
3. 本地方法栈(Native Method Stack)
与JVM stack 相似,JVM stack 为虚拟机执行JAVA方法服务,而Native Method Stack 是为虚拟机执行本地方法服务。有的虚拟机对两者没有区分,合二为一。
同样会存在两种异常: StackOverflowError 和 OutOfMemoryError 异常. (样例如第2点中)
4. JAVA 堆(Heap)
Heap 是java内存管理中最大的一块内存区域,被所有线程共享,用于存放对象实例,几乎所有的对象实例和数组都在此分配。
在JVM规范中规定,JAVA堆可以物理不联系,只要逻辑空间联系即可。这样,当堆Heap无法完成再扩展时,将会抛出:OutOfMemoryError异常。
所以,不断的创建对象,就会导致内存溢出.
/** * VM Args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError * @author yql * */ import java.util.*; public class HeapOOM { static class OOMObject{ } public static void main(String[] arg){ List<OOMObject> list = new ArrayList<OOMObject>(); while(true){ list.add(new OOMObject()); } } }
运行结果为:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Unknown Source)
at java.util.Arrays.copyOf(Unknown Source)
at java.util.ArrayList.grow(Unknown Source)
at java.util.ArrayList.ensureExplicitCapacity(Unknown Source)
at java.util.ArrayList.ensureCapacityInternal(Unknown Source)
at java.util.ArrayList.add(Unknown Source)
at HeapOOM.main(HeapOOM.java:17)
5. 方法区(Method Area)
方法区也是多线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译的代码数据。(JVM规范把方法区描述为堆的一个逻辑区域)
方法区在无法满足内存分配时,将抛出OutOfMemoryError 异常。
6. 运行时常量池(Runtime Constant Pool )
运行时常量池是方法区的一部分,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池。
/** * VM Args: -Xss2M * @author yql * */ import java.util.*; public class RuntimeConstantPoolOOM { public static void main(String[] arg) throws Throwable{ //使用List 保持常量池引用, 避免Full GC回收常量行为 List<String> list = new ArrayList<String>(); long i= 0l; while(true){ list.add(String.valueOf(i++).intern()); } } }
运行结果:
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
at java.lang.String.intern(Native Method)
at RuntimeConstantPoolOOM.main(RuntimeConstantPoolOOM.java 13)
....
7. 直接内存(Direct Memory)
本机内存分配不受JAVA 虚拟机(堆,栈等)的影响,但是受机器内存的影响,当各区域内存总和大于物理内存时,导致动态扩展内存出现:OutOfMemoryError异常。
[b]对象访问[/b]
对象访问主要有两种方式:
一种是,通过句柄访问对象;(优点在于:reference 中存储的是稳定的句柄地址,在对象被移动时,只改变句柄中实例数据指针,而reference本身不变)
一种是,通过直接指针访问对象。(优点在于:速度更快,节省了一次指针定位时间)
相关文章推荐
- chrome 切换到其他网络后重新加载网
- 孙俪自《后宫甄嬛传》爆红
- 网页被纳入Google补充结果的成因与对策——不优良的SEO的结果
- 关于运放的压摆率(SR)和GBP
- enctype="multipart/form-data 无法通过request得到值
- 贝尼奥夫和威斯
- androidpn 引用的其他jar和源码下载地址
- 聚食汇点餐为餐饮企业信息化建设提速
- Xshell的舒服配色方案,否则蓝色看不清
- NIO设置SO_LINGER引发的异常
- Android Animation动画(很详细)
- pthread_join with timeout
- 杂技
- chrome调试JS查找JS效果侦听的函数
- system 密码忘记设置解决办法
- Java中字符串操作方法总结
- opengl场景保存成BMP文件
- MPI 环境搭建
- 检测到在集成的托管管道模式下不适用的ASP.NET设置的解决方法
- JAVA笔记26-网络编程(不等于网站编程)