垃圾回收和反射技术

8
我想知道当使用反射来获取某些字段值时,垃圾回收是如何工作的。在没有使用正式语言语法访问它们的情况下,JVM如何知道这些字段引用的值是可访问的,因此当前不符合垃圾回收的条件?
以下是描述该问题的小片段(虽然这里过分强调了反射):
/**
 *
 */

import java.lang.reflect.Field;

public class B {
    protected B previous = null, next = null;

    /**
     *
     */
    public B(B from) {
        this.previous = from;
    }

    public void transition(B to) {
        this.next = to;
    }

    public B next() {
        try {
            Field f = getClass().getField("next");
            f.setAccessible(true);
            try {
                return (B)f.get(this);
            } finally {
                f.setAccessible(false);
            }
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }

    public B previous() {
        try {
            Field f = getClass().getField("previous");
            f.setAccessible(true);
            try {
                return (B)f.get(this);
            } finally {
                f.setAccessible(false);
            }
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }
}

祝福您,
克里斯


有趣的问题。它是受某种嵌入式Java应用程序的启发吗? - James T Snell
请问您能否提供一个代码片段来澄清您所说的“使用反射获取某些字段值的类”是什么意思? - Ben Burns
实际上,我正在为一个网络框架编写测试,其中一些字段是通过反射访问的。我想知道反射对内存使用有什么影响,也许是因为JVM保留了它不确定的对象。 - Chris Dennett
反射总是会增加额外的负担。例如,如果你使用反射执行方法调用,你必须先获取一个 Method 对象的引用等。这意味着你需要构建对象并执行多个其他调用(通常还有一些条件逻辑),才能执行一个方法调用。一般来说,当灵活性超过性能劣势时,你会更倾向于采用这种方法。 - Ben Burns
同意。但我正在进行涉及状态和通过代理的延迟引用的复杂操作,有点像更简单的注入版本。 - Chris Dennett
3个回答

10
如果您正在访问一个实例的字段,则仍需要引用该实例。 对于这种情况进行垃圾回收(GC)是很正常的事情。

5

要访问对象的字段,您必须拥有对该对象的引用。无论是通过反射还是直接访问它,都不会影响您是否拥有对对象的强引用。


1

这是一个有点奇怪的测试案例:您正在使用反射来访问“this”。按定义,“this”在声明类的实例方法中使用时是活动的,因此不会被GC回收。

但更重要的是,反射只是允许您操作已经具有引用的对象中的字段等。这是关键-如果您可以给Reflect要检查的实例,那么您显然仍然拥有对该对象的引用,因此它仍然存活。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接