Reputation: 418
*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;
}
}
Upvotes: 0
Views: 103
Reputation: 418
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
Upvotes: 0