深入java

深入java----垃圾回收

Java和C++之间有一睹内存动态分配和垃圾收集技术所围成的“高墙”,墙外面的人想进去,墙里面的人想出来。-------《深入理解JVM虚拟机》

 

补充:在无用对象判断这两种方法中,都是靠对象的引用进行判断对象是否无用。又因为在某些情况下我们不一定需要回收对象,因此在jdk1.2后,java对引用进行了扩充,将引用分为4类“强引用”“软引用”“弱引用”“虚引用”。

补充2:对于方法区中的垃圾回收,回收效率远远低于堆,在此区域中主要回收的内容为:无用的类以及废弃的常量。废弃常量的回收与堆中非常类似,但是无用类的回收将麻烦许多。

补充3:四种引用类型:强引用,垃圾回收不回收被引用对象。软引用,内存溢出之前列入二次回收范围。弱引用,生存到下一次垃圾回收。虚引用,对象被收集时收到一个系统通知。

下面详细说说四种回收算法。

  • 标记-清除:分为两个阶段,首先是进行无用对象判断,进而标记出所有需要回收的对象,标记完成后进行统一的对象回收。此算法为回收算法最基础算法,但是其有两个缺点,效率不高和内存碎片太多。
  • 复制:将内存分为三个区域,一块大区域eden与两块小区域survivor,每次使用只使用eden和一块survivor,回收时将eden和survivor中存活的对象复制到未使用的survivor上,然后将之前使用过的区域清除。当survivor空间不够时,借用eden区域实施算法。
  • 标记整理:首先将标记对象,然后将标记的对象向内存一端移动,然后直接清理边界之外的区域。这种算法主要适用与对象存活时间长,存活率高的情况。
  • 分代收集:将内存分为老年代和新生代,针对老年代,采用标记整理算法或标记清除算法,针对新生代,采用复制算法。因为新生代中大部分对象存活时间短,存活率极低,如果使用标记整理算法效率不高,同时老年代中对象存活时间长,存活率高,使用复制算法极大影响效率。

对于垃圾回收,还有一个重要的概念 “安全点”,他用在无用对象判断前使所有线程停止,这个停止的地方就是安全点,然后进行无用对象判断这一过程。原因简单来说,你不能在内存还是动态的过程中进行判断某个对象是否无用。

如何让线程跑到安全点呢?

首先虚拟机设置一个中断标志,然后线程去主动轮询这个标志,让发现中断为真,将自己挂起。但是这里有一个漏洞,如果线程本身是挂起状态,那么这个线程如何知道现在是垃圾回收器工作中,自己不能运行呢?这里便又引入的安全区域的概念,意思是在这个区域中,gc可以安全进行。

 下面将列出主要的垃圾收集器及其特点:

  • Serial(新生代)--Serial Old(老年代):单线程收集器,特点:简单高效。新生代采用“复制”,老年代采用“标记整理”。
  • ParNew(新生代):Serial的多线程版本,但在但CPU下,不一定效果比Serial好,其成为新生代收集器的选择一个很大原因是能与CMS收集器配合。新生代采用“复制”
  • Parallel Scavenge(新生代)--Parallel Old(老年代):吞吐量优先收集器。特点:可自适应调节回收时间,适合后台运算。
  • CMS(老年代):特点:并发收集,低停顿。
  • G1:最前沿收集器,按下不表。

目前虚拟机采用的收集器搭配方案:CMS-ParNew  Parallel Scavenge--Parallel Old  Serial Old-ParNew

 

 

深入java----java内存区域及对象的创建

看完深入理解jvm之后自己再用图的方式进行一遍梳理,用以加深理解。

 

第一部分,首先对整体java运行时内存区域有一个整体框架式的了解。

 

运行时内存区域的划分如上图所示,那么接下里看看一个对象的创建又怎么样的过程。

首先是需要一块内存区域,而寻找内存区域主要分为两种策略:

  1.   指针碰撞,当空闲内存区域为连续区域时,那么只需要将空指针移动一段与对象大小相等的距离即可。
  2.   空闲列表,当空闲内存区域不连续时,需要维护一个表来记录那些内存可用,并在分配时给对象分配一个足够大的空间并更新表。

(注:内存区域是否连续主要和垃圾回收策略相关)

在上面的过程中,对象的大小如何确定呢?这就涉及对象在内存中的存储形式是什么了。

一个java对象在内存中的结构分三块:

  1. 对象头:用于存储运行数据(类型指针,gc标志,状态锁等),大小为8字节的一倍或两倍。
  2. 实例数据:用户所需要的真正有效的数据。
  3. 对齐填充:站位用,因为要保证一个对象的大小为8字节的整数倍。

通过确定上述三个块便可确定一个对象的大小。

当一个对象创建好后,对象放在堆里,我们如何访问呢?

要访问一个对象,就需要用到java内存区域中虚拟机栈里面的局部变量表,通过局部变量表中的reference数据来访问堆上的具体对象。

posted @ 2018-07-09 11:00  zlz099  阅读(189)  评论(0编辑  收藏  举报