java虚拟机之对象的探秘

6 篇文章 0 订阅

 对于java程序员来说,在虚拟机自动内存管理理机制的协助下,不在像C++/C那样需要new创建一个对象,又要delete销毁一个对象的空间,因此不容易出现内存溢出这种情况。C++中的new和delete不容易操作,C++比较强是基于程序员本身比较牛。当然C++学的好,那么java一定没有什么问题。

C/C++手动会手垃圾 1.忘了回收(内存容易溢出) 2. 多次回收(可能销毁数据),所以java真的很香!!

 

  • 1对象是否死亡?
  • 1.1引用计数算法
  •  1.2 可达性分析算法
  • 再谈引用
  • 生存还是死亡?

 1. 对象是否死亡?

java堆里面几乎放着所有实例对象,垃圾收集器在对对象回收之前首先判断的是,对象是不是已经死亡了。如果死亡将其回收。那通过哪种方法区判断对象是否已经死亡呢?下面将是我要介绍的!!

1.1引用计数算法

计数算法,即在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一;当引用失效时,计数器值就减一;任意时刻计数器为零的对象就是不可能再被使用的。如图所示,如果有三个方法引用这个对象,按照计数算法,将其记录为三,如果有一个引用失效则,计数值减少为2.

缺点:在主流的java虚拟机里一般不用计数器算法,因为计数算法很难解决对象间相互循环利用的问题。

 1.2 可达性分析算法

当前的主流商用程序语言的内存管理子系统,都是通过可达性分析算法来判定对象是否存活的。可达性分析算法是什么?这个就比较难以理解,希望我能讲的比较明白。

基本思路就是:通过一系列“GC Roots”的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径称为“引用链”,如果某个对象到GC root间没有任何引用链相连,或者用图论来说就是从GC Root到这个对象不可达,用此作为判断对象可回收的依据。

java技术体系里,固定可作为GC ROOT的对象包括:

在虚拟机栈(栈帧中的本地变量表)中引用对象,譬如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量等。

在方法区中类静态属性引用的对象,譬如java类的引用类型静态变量。

java虚拟机内部引用,如基本数据类型对应的Class对象,一些常驻的异常对象NullPointExcepiton、OutOfMemoryErrord等,还有系统的类加载器。

所有的锁持有对象(synchronized关键字)。

反映Java虚拟机内部情况的JMXBean、JVMTI注册的回调、本地代码缓存等。

再谈引用

无论是通过哪种方法都离不开引用,所以有必要谈一谈引用,在还早的定义里是:如果reference类型的数据中存储的数值代表的是另外一块内存地址的起始值,就称之为reference数据是代表某块内存、某个对象的引用。这样的定义有点像虚拟机张的栈与堆之间的执行过程,栈取得堆中内存块的数据。但是在


大佬的定义里可不是这样的啊!看看周志明爸爸是怎么说的,

这种定义并没有什么不对,只是现在看来有些过于狭隘了,一个对象在这样定义下只有“被调用”或者“未被调用”两种状态,对于描述一些“食之无味,弃之可惜”的对象就显得无能为力。

JDK 1.2版之后Java对调用的概念进行了扩充,一共分为强引用(Strongly Re-ference)、软引用(Soft Reference)、弱引用(Weak Reference)和虚引用(PhantomReference)。

什么是强引用?就是传统意义上的引用,是指程序代码之中常见存在的引用赋值。即类似于“A a = new A()”,这种关系。

软应用是用来描述一些还在用,但是并非必须的对象。只被软引用关联着的对象,在系统将要发生内存溢出前,会把对象列为回收范围之中,如果这次回收还没有足够的内存,才会被抛出异常。

弱引用也是用来描述那些非必须对象,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生为止。当垃圾收集开始工作,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。

虚引用也称为“幽灵引用”或者“幻影引用”,它是最弱的一引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过用来取得一个对象实对象。为一个对象设置虚引用关联的唯一目的只是为了能在这个对象被收集器收回时,收到一个系统消息。

生存还是死亡?

在可达性分析中判定为不可达的对象,并不是“非死不可的”,也需要经历一个“缓刑”期。还需要经历两个阶段的判断:如果对象在进行可达性分析以后发现没有与GC Root相连的引用链,那就会被标记一次,随后进行一次筛选,筛选的条件就是此对象是否有必要执行执行finalize()方法。假如对象没有覆盖执行finalize()方法,或者执行finalize()已经虚拟机调用过,那么虚拟机将这种情况视为“没有必要执行”。

如果判定为有必要执行finalize()方法,那么对象就会被放置在F-Queue队列之中。并在稍后一条由虚拟机自动建立的、低调优先级的Finalizer线程去执行finalize()方法。

未完更新中.....................

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值