简体   繁体   中英

JDK13 Garbage Collection Not Working Correctly. Some of the de-referenced objects not being garbage collected

框图

*The implementation module is not being garbage collected after it is de-reference in UI module. I have overridden finalize method in all the classes of implementation. finalize method of none of the objects being called after dereferencing. No Thread is running in implementation module when it is de-referenced.

The below code is only to provide a perspective of project. The Set of WeakReferences in BankConfig, Main class are not part of original project. The CoreConfig and CoreController belong to implementation module. *

    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;
    }
}

The issue was caused by datakernel library used in implementation module caused due to JmxModule registering jmx-compatible components to the global jmx registry.

Reference : datakernel issue #17

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM