2

我正在使用一些相当重的反射来检查和遍历类库。我想提取和修改字段 - 静态和实例。静态字段易于查找和修改;我可以收集课程,询问他们的字段列表,记录字段并检查/更改它们的值。

实例字段不同。我可以收集对其 Field 对象的引用,但为了更改它们的值,我需要运行实例化该类型对象的代码。假设我们不知道这段代码做了什么,但是我们有一些方法 blackBox() 实例化一些对象,运行一些代码,使用我们感兴趣的库做一些事情。在它运行之后,我想找到一个实例班级,C.

如果我收集所有静态字段的列表,并通过它们的引用进行足够远的迭代,我最终会在代码中找到所有活动的实例吗?也就是说,我提议:

对于在 Java 程序中实例化的所有未进行垃圾回收的对象,存在一个以静态字段开始并以该对象结束的引用链。

这是关于 Java 程序的一般规则吗?

编辑:两个额外的限定词:

  1. 我只对不产生线程的顺序程序感兴趣。
  2. 我假设 blackBox() 已完成处理,并且垃圾收集器已运行。稍后我们可能希望使用库 (moreBlackBox()) 执行更多代码 - 想象一个应用程序已启动,现在已暂停。
4

2 回答 2

3

不。要么你有一个从静态字段开始的引用链,要么(而且可能更常见)你有一个从线程堆栈上的局部变量开始的引用链:

public static void main(String[] args) {
    Foo foo = new Foo();
    doSomethingWithFoo(foo);
}

在上面, foo 实际上可能会递归地引用一大堆其他对象,并且它们都不能被 GC 收集,因为主线程foo的堆栈中仍然有局部变量。

于 2012-09-24T15:27:55.747 回答
0

这可能是一个很好的起点:

并发收集器在并发收集周期中暂停应用程序两次。第一个暂停是标记从根(例如,线程堆栈上的对象、静态对象等)和堆中的其他地方(例如,年轻代)直接可访问的对象为活动的。这个第一次暂停被称为初始标记。第二次暂停出现在标记阶段的末尾,并查找在并发标记阶段由于应用程序线程的并发执行而丢失的对象。第二次停顿称为备注。

如需更深入的阅读,请考虑:

Oracle 垃圾收集器文档

于 2012-09-24T15:34:29.193 回答