Thinking in Java---初始化与清理

1、初始化顺序

 1)当首次创建一个新的对象的时候,或者是静态方法或者是属性第一次被访问时候,Java解释器就会尝试去定位相应的.class 文件。

 2)载入.class 文件,有关静态初始化的动作都会在这个阶段执行。但是静态初始化只是在对象第一次载入的时候做一次初始化。

 3)当用new新建对象的时候,Java虚拟机就会在堆上为对象分配足够的空间,并且将分配的空间清0。并将所有的属性初始化为默认值(数字类型初始化为0,而对象类型初始化为null)。

 4)执行所有出现在属性定义处的初始化数据。

 5)执行构造方法。


2、Java的垃圾回收机制

 1)垃圾回收对于提高对象的创建速度,具有明显的效果。

 2)要更好的理解垃圾回收器(GC)的工作模式,才能明白为什么Java采用在堆上分配对象的内存。

      “引用计数”是一种简单但速度很慢的垃圾回收技术。每一个对象都有一个引用计数器,当有引用链接到对象的时候,相应的计数器就会加1。同理,当引用离开作用域或者是引用被置为0的时候,相应的计数器就会减1。垃圾回收器会在含有全部对象的列表上遍历,当发现某一个对象的引用计数为0的时候,就释放占用的空间。

       但是由于“引用计数”非常慢,并且有“应该被回收,但是引用计数不为0”的缺陷,所以它从来都没有被用在任何一种Java虚拟机的实现中。实际上应用的技术思想是:对于任何“活”的对象,一定能够追溯到期存活在堆栈或者是静态存储中的引用。因此,如果从堆栈或者是静态存储开始,遍历所有的引用,就能找到所有的“活”的对象。Java采用的是一种基于“自适应”的算法是实现垃圾回收的。至于如何找到存活的对象并且处理他们,取决于Java虚拟机实现的方式。常用的方式有两种:stop and copy(停止--复制)和mark and sweep(标记--清扫);

       stop and copy显然就说,要暂停程序的运行(所以它不属于后台回收模式),然后将所有存活的对象复制到另一个堆,没有被复制将被当作是垃圾。当对象被复制到新的堆的时候,他们是一个挨着一个,所以新的堆也是紧凑的。但是这样会产生两个新的问题:第一个问题是:在两个堆之间相互复制,从而会比实际多维护一倍的空间。第二个问题在于复制,程序进入稳定状态之后,就只会产生很少的垃圾碎片。而这种复制式的垃圾回收器依然需要将对象从内存的一个位置复制到另外的一个位置,这样非常浪费。为了避免这种浪费,产生了mark and sweep模式。它对堆进行检查,如果没有垃圾产生就会自动切换到另外一种模式“自适应”。“标记--清扫”所依据的思路也是从堆或者是静态存储出发,遍历所有的对象,进而找出存活的对象,每当它找到一个存活的对象的时候,就给他一个标记。但是这个时候,并不进行垃圾回收。只有在所有的标记工作都完成的时候,清理工作才正式的开始。在清理的过程之中,没有被标记的对象就会被清理掉。这样一来,剩下的内存区域就不是连续的,必须要进行一次紧凑处理。

       总而言之,Java虚拟机会对内存进行监视,当发现对象都很稳定,就会切换到“mark and sweep”模式,同样Java虚拟机会监视“标记--清扫”的结果,要是堆空间出现很多的碎片的话,就自动的切换到”stop and copy“的模式。结合这二者,就是一种”自适应“的,分代的,停止--复制,标记--清扫式的垃圾回收器。


      此外,Java虚拟机中还有很多的附加技术用以提升速度。尤其是与加载相关的,被称为”及时(Just-in-Time,JIT)“编译器的技术。


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。