java虚拟机,深入理解java虚拟机学习笔记1.

工作2年,对这块,不曾了解,惭愧惭愧,后来在别人的推荐下、,买来看了看,感觉还不错。
记录下笔记吧。看了下书,在自己理解的程度下,将书上的例子,弄过来了。供以后没事的时候,再看。
如果不对,还麻烦各位同行指出来,不胜感激。
今天看的,是第二章java内存区域与内存溢出异常,自己用word模仿画了个图。
深入理解java虚拟机学习笔记1.java虚拟机
各数据区域功能(重要,后面的例子会讲到。s):
数据区域图中,除了方法区和堆区是线程共享区外,其他三个是线程隔离的数据区(private)
程序计数器(Program Counter Register):属于线程私有的,占用的内存空间较少,可以看成是当前线程所执行字节码的行号指示器,字节码解释器工作时就是通过改变这个计数器的值来选择下一条,需要执行的字节码指令,分支,循环,跳转,异常处理,线程恢复等基础功能需要依赖这个计数器来完成,这个区域是jvm规范中没有规定任何OutOfMemoryError情况区域
堆(Heap):jvm中内存占用最大的一块,是所有线程共享的一块内存区域.在jvm启动时创建,存放的是所有对象实例(或数组),所有的对象实例都在这里进行动态分配,当类空间无法再扩张会抛出OutOfMemoryError异常
方法区(Method Area):与堆类似,也是各个线程共享的内存区域,主要用途,用来存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据,当方法区无法满足内存分配时,也抛出OutOfMemoryError异常
虚拟机栈:和程序计数器一样,都属于线程私有,生命周期与线程相同,描述的是java方法执行的内存模型,每个方法执行都会创建一个栈帧,用于存储局部变量表,操作栈,动态链接,方法出口等信息,每一个方法被调用直至执行完成的过程,就对应一个栈帧在jvm stack 从入栈到出栈的过程.局部变量表存放了编译期可知的各种数据基本类型(Boolean,byte,char,short,int,float,long,double),以及对象的引用。这个区域中定义了2种异常情况,如果线程请求的栈深度大于jvm所允许的深度,将抛出StackOverflowError异常,如果jvm可以动态扩张,当扩张无法申请到足够的内存空间是会抛出OutOfMemoryError异常。(这些数据区域异常将在下面的例子都讲到)。
本地方法栈:与虚拟机栈比较相似。不再描述。
上面的写的太理论化,不形象,看下这个例子就明白了。
Java栈,java堆,java方法区,三者有何关系?请看如下代码
Object object = new Object();
Object object 这部分存储在java栈的本地变量表中,作为一个引用(reference)类型存在
new Object() 这部分存储在java堆中,形成了一块存储了Object类型所有的实例数据值的结构化内存,动态变化,长度不固定。
方法区:在java堆中,必须要找到此对象类型数据,比如,对象类型,基类,实现的接口,方法等(可不可以理解成对象的所有数据结构都存在这里?)都存放在方法区。
2.关于OutOfMemoryError异常的几个例子:
A.java堆溢出:
上面讲过,java堆是用来存储对象实例的,只要不停创建对象, gc来不及回收,为了体现效果,在eclipse jvm args 设置了最少120M和最大1024M的内存占用参数。
深入理解java虚拟机学习笔记1.java虚拟机
1 import java.util.ArrayList; 2 import java.util.List; 3 4 public class TestHeapOOM { 5 /** 6 * vm args -Xmn120M -Xmx1024M 7 */ 8 public static void main(String[] args) { 9 List list = new ArrayList(); 10 while(true){ 11 list.add("sss"); 12 } 13 } 14 }

运行结果:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Unknown Source)
总结:java 堆OutOfMemoryError异常,如果出现内存溢出,除了有java.lang.OutOfMemoryError,后面来还有java heap space提示信息。
当然,堆还有一种内存泄露,与内存溢出不同的是,这可能会是垃圾收集器无法自动回收造成的,这种情况要通过分析工具,具体分析才能定位。
2.jvm栈和本地方法栈的溢出
看这个前,请重新看下各数据区域功能jvm栈和本地方法栈的描述。
看完描述,结合代码来说明。
A:StackOverflowError例子,需要设置的参数-Xss
深入理解java虚拟机学习笔记1.java虚拟机
/** * jvm args -Xss10M */ public class TestStackSOF { public long stackLenth = 1; public void stackSOF(){ stackLenth++; stackSOF(); } public static void main(String[] args) { TestStackSOF tss = new TestStackSOF(); try{ tss.stackSOF(); }catch(Throwable e){ System.out.println("stackLenth: "+tss.stackLenth); try { throw e; } catch (Throwable e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } }

执行的结果:
stackLenth: 326323
java.lang.StackOverflowError
at com.cn.TestStackSOF.stackSOF(TestStackSOF.java:9)
at com.cn.TestStackSOF.stackSOF(TestStackSOF.java:9)
如果把-Xss调到50M,执行的结果是:
stackLenth: 1637043
java.lang.StackOverflowError
at com.cn.TestStackSOF.stackSOF(TestStackSOF.java:9)
at com.cn.TestStackSOF.stackSOF(TestStackSOF.java:9)
总结:不难看出,-Xss大小不一样,执行的结果也不一样。如果以后在项目中遇到
java.lang.StackOverflowError异常,可以先检查代码是否有无限递归,如果不是,
可加大-Xss大小再看运行效果
方法区溢出:解题用动态代理产生大量的类,jvm args设置的参数
–XX:PermSize=10M –XX:MaxPermSize=10M
(代码,有时间再补上。)



Tags:  java虚拟机

延伸阅读

最新评论

发表评论