Java的GC机制
来源:互联网 发布:万网域名登陆 编辑:程序博客网 时间:2024/06/07 23:48
jVM内存模型
java和C/C++最大的一个区别就是自动的内存回收机制。Java的内存模型经典图例如下:
这里重点注意三个地方:堆内存、方法区、与栈内存。其中堆内存与方法区又合称为堆内存。在程序未实例化之前,类的模型以及全局变量都是保存在方法区中。类的加载方法分为两种:
显式加载:Class.forName()利用Class的静态方法对类进行实例化。隐式加载:通过new关键字加载。
当类实例化之后,实例就按照方法区类的模板加载到了堆内存。此时栈内存存放基本的数据类型(int,float,short,long,char等)以及指向堆对象的引用变量。总之,堆是用来存放对象的,栈是用来执行程序的,相较于堆,栈的执行速度较快。
这里需要重点注意的是Java中的常量池。由于版本原因,运行时常量池在JDK1.6及之前版本的JVM中是方法区的一部分,而在HotSpot虚拟机中方法区放在了”永久代(Permanent Generation)”。所以运行时常量池也是在永久代的。 但是JDK1.7及之后版本的JVM已经将运行时常量池从方法区中移了出来,在Java 堆(Heap)中开辟了一块区域存放运行时常量池。
这里拿int变量与string变量来作为例子。int与string变量最大的区别就是int存在它自身的基本数据类型,在int,integer,new integer()之间存在相对复杂的变化。
int:
基本数据类型与对象间比较,在JDK1.5以后存在自动拆箱机制,不论后面其它哪个相比较,都会被向下转型到int,然后比较其数值。
Integer与Integer间的比较,从jdk1.5开始,有“自动装箱”这么一个机制,在byte-128到127范围内,如果存在了一个值,再创建相同值的时候就不会重新创建,而是引用原来那个,但是超过byte范围还是会新建的对象。
关于new integer() 这里涉及到和int比较不再赘述,都自动拆箱比较数值。但和integer进行比较的时候,当integer在integer cache中时候,显然不等,当超出integer cache范围时候,此时integer相当于new integer()两个new比较都在堆中创建了对象,对应不同的地址,显然不相等。
public class test { public static void main(String[] args) { int i0=1000; Integer i1=1000; Integer i2=1000; Integer i3=2000; Integer i11=new Integer(1000); Integer i22=new Integer(1000); Integer i33=new Integer(2000); System.out.println(i0==i11);//true System.out.println(i0==i1);//true System.out.println(i1==i2);//false不会有自动拆箱 System.out.println(i1==i11);//false System.out.println(i11==i22);//false System.out.println(i3==(i1+i2));//true后面的这些加加减减全部都拆箱为基本数据类型。 System.out.println(i3==(i11+i22));//true System.out.println(i33==(i1+i2));//true System.out.println(i33==(i11+i22));//true }}
string:
问:String s = new String(“xyz”); 产生几个对象?答:一个或两个。如果常量池中原来没有 ”xyz”, 就是两个。如果原来的常量池中存在“xyz”时,就是一个。
字符串加法:JVM对于字符串常量的”+”号连接,将程序编译期,JVM就将常量字符串的”+”连接优化为连接后的值。由final修饰和无final修饰:有final修饰的字符串能在编译前确定,无final修饰的字符串是无法在编译前确定的。
//字符串相加JVM优化String a = "a1"; String b = "a" + 1; System.out.println((a == b)); //result = true String a = "atrue"; String b = "a" + "true"; System.out.println((a == b)); //result = true String a = "a3.4"; String b = "a" + 3.4; System.out.println((a == b)); //result = true //字符串相加无final关键字String a = "ab"; String bb = "b"; String b = "a" + bb; System.out.println((a == b)); //result = false //字符串相加有final关键字String a = "ab"; final String bb = "b"; String b = "a" + bb; System.out.println((a == b)); //result = true
Java中的内存溢出
首先我们来区别两个概念:
内存溢出:程序在申请内存空间时,没有足够的内存空间供其使用。内存泄漏:程序在申请内存后,无法释放已经申请的内存空间。
沿袭上述所述,Java中的堆的溢出,主要原因就是对象实例化过多。栈的溢出主要是因为线程需要栈深度大于虚拟机本身。这里尤其注意在多线程的环境之中,可以通过减小最大堆和减小栈容量来创建更多的线程。
关于内存泄漏,常见原因是对象在使用后没有断开引用。例如(1)各类连接如SQL、IO。(2)变量不合理的作用域。(3)面试常考:单例设计模式也会导致内存泄漏。
//核心:单例模式中存在对于指向其它实例的指针class Bigclass{ //class body}class Singleton{ private Bigclass bc; private static Singleton instance=new Singleton(new Bigclass()); private Singleton(Bigclass bc){this.bc=bc} public Singleton getinstance{ return instance; }}
关于GC机制
判断方法
引用计数法:略。无法解决互相引用的问题。可达性分析法:通过一系列的 gc root(栈指针,方法区中static相关已经常量引用) 进行树搜索。
回收算法
标记-清除法:效率问题以及内存碎片。复制算法:仅仅使用1/2内存。内存开销较大。但实际上98%的对象是朝生夕死的,所以不需要按照1:1的比例划分,而是以8:1的比例(hotspot默认)划分为Eden和survivor。分代收集法:jvm中的GC算法。新生代采用复制算法,因为有大量对象死去。老年代采用标记整理或者标记清除。
回收内存模型:
由分代收集再谈几类引用:
强引用:怎么都不会被GC机制回收。宁愿报错都不会回收该区域。软引用:只有在内存不足时,才会被回收。JDK1.2以后提供softreference类。弱引用:weak为关键字(weakhashmap),一旦运行system.gc()则立马被回收虚引用:就和没有引用一样。
system.gc()与finalize
system.gc()调用的是runtime中的gc方法。对象回收前会调用finalize方法,但也只会调用一次,此时可以通过finalize 完成引用对自我进行最后一次拯救(参见《深入理解JVM》)。不同于C++中的析构函数,C++调用析构函数对象一定会被销毁。
此外调用GC时会STOP THE WORLD现象,因为不能存在在垃圾回收时,引用关系还在不断变化的情况。这里又引入了安全点的概念。所谓安全点,是以是否具有让程序具有长时间执行的特征来选定的。如一些循环操作。在随后运行GC时又存在抢先式中断和主动式中断。注意其中概念与区别。目前的hotspot主要采取主动式中断轮询各个线程是否到达安全点。
fullgc与minor gc:
Minor GC:当Eden区满时,触发Minor GC。
Full GC:
(1)调用System.gc时,系统建议执行Full GC,但是不必然执行
(2)老年代空间不足
(3)方法去空间不足
(4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存
(5)由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小
- Java的GC机制
- Java的GC机制
- Java的GC机制
- Java的GC机制
- Java的GC机制
- Java的GC机制
- Java的GC机制
- Java的GC机制
- Java的GC机制
- Java的GC机制
- Java的GC机制
- 【转载】Java的GC机制
- Java的GC机制详解
- Java的GC回收机制
- java的GC机制--javaGC机制
- Java的垃圾回收器GC机制
- .Java的垃圾回收机制(GC)
- Java的GC机制及算法
- +-字符串
- MFC中char 转CString
- 内连接 左外连接 右外连接 交叉连接
- 【05】淘淘商城-内容分类管理 修改、删除实现、内容列表展示
- hdu-4565(矩阵快速幂+推导)
- Java的GC机制
- BackTrack5 学习笔记9 Metasploit
- Java基础面试题一:请说说抽象类和接口的区别?
- C#基础-030 数组练习题
- Cassandra3.110+Python2.7.3 Windows安装
- OSG 粒子系统 类图
- MySQL 历史版本安装和下载
- 邮件是怎么发送和接收的(STMP和POP3/IMAP协议)
- IOS 动画用法总结