0

框图

*实现模块在 UI 模块中被取消引用后不会被垃圾收集。我已经在所有实现类中重写了 finalize 方法。取消引用后不调用任何对象的 finalize 方法。取消引用时,实现模块中没有线程正在运行。

下面的代码只是提供一个项目的视角。BankConfig,Main 类中的 WeakReferences 集不是原始项目的一部分。CoreConfig 和 CoreController 属于实现模块。*

    public class BankConfig {

    public final String uuid = UUID.randomUUID().toString();
    public final String name;
    public Controller   controller;

    public BankConfig(String name, Controller controller) {
        this.name       = name;
        this.controller = controller;
    }

    @SuppressWarnings("deprecation")
    @Override
    protected void finalize() throws Throwable {
        System.out.println("garbage collected : "+uuid);
        super.finalize();
    }

    @Override
    public String toString() {
        return "bank-"+uuid;
    }
}

public interface Controller {

    public abstract BankConfig getBankConfig();
}


public class CoreConfig extends BankConfig {

    public CoreConfig(String name,Controller controller) {
        super(name, controller);
    }

    public CoreConfig(BankConfig bankConfig) {
        super(bankConfig.name, bankConfig.controller);
    }

    public CoreConfig(BankConfig bankConfig, final Controller controller) {
        super(bankConfig.name, controller);
    }
    @Override
    public String toString() {
        return "core-"+uuid;
    }

}


public class CoreController implements Controller {

    public final CoreConfig config;

    public CoreController(BankConfig config) {
        this.config = new CoreConfig(config, this);
    }

    @Override
    public BankConfig getBankConfig() {
        return config;
    }
}



public class Main {

    private static final Set<WeakReference<BankConfig>> WEAK_REFERENCES = new HashSet<>();
    public static final ObservableList<BankConfig> banks = FXCollections.observableArrayList();

    static {
        banks.add(readConfigFromDatabase("krishna"));
        banks.add(readConfigFromDatabase("shankar"));
    }

    public static void main(String[] args) throws InterruptedException {
        banks.add(loadController(readConfigFromDatabase("krishna")).getBankConfig());
        banks.add(loadController(readConfigFromDatabase("shankar")).getBankConfig());

        for (BankConfig bankConfig : banks) {
            WEAK_REFERENCES.add(new WeakReference<BankConfig>(bankConfig));
        }
        banks.clear();

        for (int i = 0; i < 5; i++) {
            System.out.println("strong references : "+banks);
            System.out.println("weak references   : "+WEAK_REFERENCES.stream().filter(ref -> ref.get() != null).map(ref -> ref.get()).collect(Collectors.toSet()));
            System.gc();
            Thread.sleep(5000);
        }
    }

    public static final Controller loadController(final BankConfig config) {
        try {
            final List<String> moduleNames = List.of("implementation");
            final URLClassLoader loader          = new URLClassLoader(new URL[0]);
            final Configuration  configuration   = ModuleLayer.boot().configuration().resolveAndBind(ModuleFinder.of(Path.of(new URL("path to implementation jar").toURI())), ModuleFinder.of(), moduleNames);
            final ModuleLayer    moduleLayer     = ModuleLayer.boot().defineModulesWithOneLoader(configuration, loader);
            final Optional<Module> module        =  moduleLayer.findModule("implementation");
            final Class<?>       controllerClass = module.get().getClassLoader().loadClass("implementation.CoreController");
            final Controller controller = (Controller) controllerClass.getConstructors()[0].newInstance(config);
            return controller;
        } catch (Exception e) {e.printStackTrace();}
        return null;
    }

    public static BankConfig readConfigFromDatabase(final String name) {
        if("krishna".equals(name)) return new BankConfig("krishna", null);
        else if("shankar".equals(name)) return new BankConfig("shankar", null);
        return null;
    }
}
4

1 回答 1

0

该问题是由于JmxModule将 jmx 兼容组件注册到全局 jmx 注册表而导致的实现模块中使用的数据内核库引起的。

参考:数据内核问题 #17

于 2020-01-31T17:43:12.120 回答