在静态变量中引用子类

问题描述 投票:0回答:2

Intellij 检查工具警告在静态变量中引用子类不是一个好的做法,因为它可能会导致死锁。使用以下文字:

此检查报告的类引用了它们自己的子类 它们的静态初始值设定项或静态字段中。此类参考文献可以 在多线程环境中导致 JVM 级死锁,当一个 线程尝试加载超类,另一个线程尝试加载 同时子类化。

以下示例说明:

class Generator {

    public static Generator fiveGenerator = new FixedGenerator(5);

    public static Generator sixGenerator = new FixedGenerator(6);

    int generateNumber() {
        //some generation code
        return 1;
    }

    private static class FixedGenerator
            extends Generator {

        FixedGenerator(int num) {
            this.num = num;
        }

        @Override
        int generateNumber() {
            return this.num;
        }

        private int num;
    }
}

请注意:

  • FixedGenerator
    课程是而且应该是私人的。

  • fiveGenerator
    sixGenerator
    是并且应该是公开的。

对此我有两个问题:

  • 这是一种不好的做法吗?为什么?这怎么会造成死锁呢?

  • 等效代码实现该功能的正确方法是什么?

java deadlock
2个回答
1
投票

这段代码不会导致任何死锁。
死锁和并发有关,你没有并发。
可能有一个初始化问题,但你也不会,因为你没有循环,因为

FixedGenerator()
调用
Generator()
Generator()
不调用
FixedGenerator()

这是一种不好的做法吗?

这是因为类不应该引用/知道它们的子类。

等效代码实现该功能的正确方法是什么?

您可以避免私有类中的继承。
作为替代方案,您可以选择组合而不是继承。


0
投票

在超类的静态初始化器中引用子类确实会在 JVM 中造成死锁。这个问题很久以前就被报告过,并被关闭为“不是错误”或“无法修复”,请参阅:

Java 1.2 和 1.4 报告了该问题,但在最新的 JVM 中仍然会出现该问题。例如,以下代码在 Java 8、11、17 和 21 中始终挂起:

public class Test {

    public static void main(String[] args) {
        List<Thread> threads = new ArrayList<>();
        for (String classname : new String[]{"A", "B", "C", "D", "E"}) {
            threads.add(new Thread(() -> {
                try {
                    Class<?> cls = Class.forName(classname);
                    System.out.println(cls.getName() + " initialized");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }));
        }

        threads.forEach(Thread::start);
    }
}

class A {
    static B b = new B();
    static C c = new C();
    static D d = new D();
    static E e = new E();
}

class B extends A {}
class C extends A {}
class D extends A {}
class E extends A {}

如果没有同时访问类层次结构,JVM 将不会挂起。

© www.soinside.com 2019 - 2024. All rights reserved.