Vic*_*aga 2 java garbage-collection memory-leaks
我知道在Java中的垃圾收集期间,没有任何对它们的引用的对象被标记为"死",以便它们可以被垃圾收集器从内存中删除.
我的问题是,在垃圾收集阶段,是否所有"死"对象都从内存中删除或者其中一些存活?为什么"死"对象会在垃圾收集阶段存活下来?
稍后编辑
谢谢你的所有答案.我可以推断出"死"对象不会被删除的主要原因是由于垃圾收集器运行方式的时间或间隔限制.但是,假设垃圾收集器可以到达所有"死"对象,我想知道是否有一种方法可以声明,引用,使用,取消引用等等.一个对象,以便它会以某种方式跳过删除阶段,即使它"死了".我想也许属于具有静态方法或内部类的类的对象或类似的东西可能由于某种原因保存在内存中,即使它们没有引用它们.
这种情况可能吗?
谢谢
我的问题是,在垃圾收集阶段,是否所有"死"对象都从内存中删除或者其中一些存活?为什么"死"对象会在垃圾收集阶段存活下来?
目前所有的HotSpot GC都是世代收藏家.引自维基百科:
"经验已经观察到,在许多程序,最近创建的对象也是那些最有可能迅速成为不可达(被称为婴儿死亡率或代假设).分代GC(又称短暂GC)对象划分为代并且,在大多数周期中,只将一代子集的对象放入初始白色(被判定的)集合中.此外,运行时系统通过观察引用的创建和覆盖来维护引用何时跨代的知识.当垃圾收集器运行时,它可能能够利用这些知识去证明,在最初的白色集中的某些对象不可达,而不必遍历整个参考树.如果代假说认为,这将导致更快的回收周期,同时还回收最不可达的对象".
这对你的问题意味着大多数GC周期只收集年轻一代的垃圾对象.最老一代的垃圾对象可以在多个GC循环中存活......直到最终收集旧一代.(在新的G1 GC中,显然老一代一次收集了一些......这可以进一步延迟回收.)
(理论上)无法访问的对象生存的其他原因包括:
带有(未执行的)终结器的无法访问的对象由垃圾收集器附加到终结队列,以便在GC完成后进行处理.
软引用,弱引用或虚拟引用的对象实际上仍然可以访问,并且在GC完成后由它们各自的引用队列管理器处理.
可通过JNI全局引用等到达的对象,等等.(谢谢@bestss)
存在涉及实例,它们的类和它们的类加载器的各种隐藏引用.
内部实例与其外部实例存在隐藏引用.
从类到内部String对象的隐藏引用表示其字符串文字.
但是,这些都是可达性定义的结果:
"可到达的对象是任何可以从任何活动线程继续计算中访问的对象." - JLS 12.6.1
值得注意的是,GC的规则对它们有一些保守的要素.他们说可访问的对象不会被删除,但他们并没有说会删除(严格地)无法访问的对象.这允许无法访问对象但运行时系统无法解决的情况.
你的后续问题:
然而,假如垃圾收集器能达到所有的"死"的对象,我在想,如果有申报的方式,参考,使用间接引用,等对象,从而在某种程度上它会跳过删除阶段,即使它"死了".
"死"并不是一个定义明确的术语.如果垃圾收集器可以到达对象,则根据定义它们是可到达的.它们仍然可以访问时不会被删除.
如果它们都是死的并且可以访问(无论"死"意味着什么!)那么它们是可达的这一事实意味着它们不会被删除.
你提出的建议没有意义.
我想也许属于具有静态方法或内部类的类的对象或类似的东西可能由于某种原因保存在内存中,即使它们没有引用它们.这种情况可能吗?
静态方法没有引用...除非它们碰巧在调用堆栈上.然后局部变量可能包含引用,就像任何其他方法调用一样.正常可达性规则适用.
只要类本身存在,静态字段就是GC根.正常可达性规则适用.
从GC的角度来看,内部类的实例与其他类的实例没有什么不同.可以在内部类实例中引用外部类实例,但这会导致正常的可访问性.
总之,可达性有一些意想不到的"原因",但它们都是可达性定义的逻辑结果.
| 归档时间: |
|
| 查看次数: |
11447 次 |
| 最近记录: |