Improve object tracking configurations

This commit is contained in:
mcrcortex
2024-08-06 23:15:57 +10:00
parent 377c51f365
commit 082143ed15

View File

@@ -3,6 +3,10 @@ package me.cortex.voxy.common.util;
import java.lang.ref.Cleaner; import java.lang.ref.Cleaner;
public abstract class TrackedObject { public abstract class TrackedObject {
//TODO: maybe make this false? for performance overhead?
public static final boolean TRACK_OBJECT_ALLOCATIONS = System.getProperty("voxy.ensureTrackedObjectsAreFreed", "true").equals("true");
public static final boolean TRACK_OBJECT_ALLOCATION_STACKS = System.getProperty("voxy.trackObjectAllocationStacks", "false").equals("true");
private final Ref ref; private final Ref ref;
public TrackedObject() { public TrackedObject() {
this.ref = register(this); this.ref = register(this);
@@ -13,8 +17,10 @@ public abstract class TrackedObject {
throw new IllegalStateException("Object " + this + " was double freed."); throw new IllegalStateException("Object " + this + " was double freed.");
} }
this.ref.freedRef[0] = true; this.ref.freedRef[0] = true;
if (TRACK_OBJECT_ALLOCATIONS) {
this.ref.cleanable.clean(); this.ref.cleanable.clean();
} }
}
public abstract void free(); public abstract void free();
@@ -30,28 +36,38 @@ public abstract class TrackedObject {
public record Ref(Cleaner.Cleanable cleanable, boolean[] freedRef) {} public record Ref(Cleaner.Cleanable cleanable, boolean[] freedRef) {}
private static final Cleaner cleaner = Cleaner.create(); private static final Cleaner cleaner;
static {
if (TRACK_OBJECT_ALLOCATIONS) {
cleaner = Cleaner.create();
} else {
cleaner = null;
}
}
public static Ref register(Object obj) { public static Ref register(Object obj) {
boolean[] freed = new boolean[1];
Cleaner.Cleanable cleanable = null;
if (TRACK_OBJECT_ALLOCATIONS) {
String clazz = obj.getClass().getName(); String clazz = obj.getClass().getName();
Throwable trace; Throwable trace;
if (true) { if (TRACK_OBJECT_ALLOCATION_STACKS) {
trace = new Throwable(); trace = new Throwable();
trace.fillInStackTrace(); trace.fillInStackTrace();
} else { } else {
trace = null; trace = null;
} }
boolean[] freed = new boolean[1]; cleanable = cleaner.register(obj, () -> {
var clean = cleaner.register(obj, ()->{
if (!freed[0]) { if (!freed[0]) {
System.err.println("Object named: " + clazz + " was not freed, location at:\n"); System.err.println("Object named: " + clazz + " was not freed, location at:\n");
if (trace != null) { if (trace != null) {
trace.printStackTrace(); trace.printStackTrace();
} else { } else {
System.err.println("Enable error tracing"); System.err.println("Enable allocation stack tracing");
} }
System.err.flush(); System.err.flush();
} }
}); });
return new Ref(clean, freed); }
return new Ref(cleanable, freed);
} }
} }