`
haitaoandroid
  • 浏览: 26441 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

JVM内存模型及垃圾收集简介

 
阅读更多

一:java内存区域和内存溢出测试

java内存分为线程共享的区域(方法区,堆)和线程不共享的区域(虚拟机栈,本地方法栈,程序计数器):

1,方法区:存放类信息,常量,静态变量,即时编译后的代码等。产生大量的类来填充方法区来测试方法区内存溢出。

2,堆:对象实例,包括数组。如果想要堆内存溢出,直接新建大量对象,然后保持对它的引用便可以了,

3,虚拟机栈:局部变量表(基本数据类型和对象引用),操作数栈,动态链接,方法出口等。因为没一个方法都是一个栈帧,大量的循环调用方法,必然会产生虚拟机栈溢出。

4,本地方法栈:类似虚拟机栈,执行native方法,具体不详。

5,程序计数器:当前线程执行的字节码的行号指示器。

书中有个好例子:

如果在一个方法A中有这么一句: Object obj = new Object(); 那么当执行A方法的时候,在当前线程的虚拟机栈中会开辟一个新的栈帧,Object obj 这句话会在栈帧中声明一个变量,反应到jvm中便是在虚拟机栈中有一个对象引用reference类型数据出现在栈帧中,new Object()是新建一个对象,自然会在堆中开辟一片区域,用来存放这个对象,obj对象属于Object这个类,这个Object类的名字,实现的接口,有哪些方法等这些类的信息都存放在方法区中,堆中的对象会有一个指针指向方法区中的Object类。

二:垃圾收集和对象分配

怎么判断对象应该被回收,两种方法:引用计数和根搜索算法,引用计数解决不了循环引用的问题,根搜索算法的根节点有如下几种:
1:本地变量表引用的对象

2:方法区中的类静态属性引用的对象

3:方法区中的常量引用的对象

4:本地方法栈中jni的引用的对象

基本的垃圾收集算法有三种:
1:标记清除算法,就是先用上面的方法标记,然后统一清除,缺点是会产生大量的碎片。

2:标记整理算法,算法是标记完一个对象后直接把这个对象移动到整个内存区域的另一端,然后整体清除内存。

3:复制算法,用一半来存对象,收集时把存活下来的复制到另一半,当然一半的比例可以调整,当大量的对象存活时效率较低,所以可以用在新生代,因为新手代的对象存活较低。

现在流行的把堆内存分代,按照对 象的存活年龄来分为新生代和老年代,新手代的对象存活时间较短,用复制算法比较好,因为每次复制的对象很少,老年代可以用标记清除和标记整理,因为一般存活的对象较多,需要做清除操作比较少。


参考:《深入理解java虚拟机》周志明


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics