diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift index 0b0fb8dc..ff114b22 100644 --- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift +++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift @@ -27,7 +27,6 @@ extension JNISwift2JavaGenerator { "org.swift.swiftkit.core.util.*", "org.swift.swiftkit.core.collections.*", "java.util.*", - "java.util.concurrent.atomic.AtomicBoolean", // NonNull, Unsigned and friends "org.swift.swiftkit.core.annotations.*", @@ -282,6 +281,7 @@ extension JNISwift2JavaGenerator { } printer.print( """ + this.$cleanup = $createCleanup(); // Only register once we have fully initialized the object since this will need the object pointer. swiftArena.register(this); @@ -317,16 +317,16 @@ extension JNISwift2JavaGenerator { /** Pointer to the "self". */ private final long selfPointer; - /** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */ - private final AtomicBoolean $state$destroyed = new AtomicBoolean(false); + /** Tracks whether this instance has been destroyed; doubles as the destroyed-state holder. */ + private final SwiftInstanceCleanup $cleanup; public long $memoryAddress() { return this.selfPointer; } @Override - public AtomicBoolean $statusDestroyedFlag() { - return $state$destroyed; + public SwiftInstanceCleanup $cleanup() { + return $cleanup; } """ ) diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/AutoSwiftMemorySession.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/AutoSwiftMemorySession.java index 36e73209..3d3d5096 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/AutoSwiftMemorySession.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/AutoSwiftMemorySession.java @@ -50,7 +50,7 @@ public void register(SwiftInstance instance) { // We make sure we don't capture `instance` in the // cleanup action, so we can ignore the warning below. - var cleanupAction = instance.$createCleanup(); + var cleanupAction = instance.$cleanup(); swiftCleaner.register(instance, cleanupAction); } } \ No newline at end of file diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java index 3514d9c1..7363539c 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/ConfinedSwiftMemorySession.java @@ -54,7 +54,7 @@ public void close() { public void register(SwiftInstance instance) { checkValid(); - SwiftInstanceCleanup cleanup = instance.$createCleanup(); + SwiftInstanceCleanup cleanup = instance.$cleanup(); this.resources.add(cleanup); } diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java index 01734d75..7c8c8934 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstance.java @@ -54,11 +54,13 @@ public interface JNISwiftInstance extends SwiftInstance { */ long $typeMetadataAddress(); - @Override + /** + * Build a fresh {@link SwiftInstanceCleanup} for this instance. + *

+ * Concrete implementations are expected to call this once during construction + * and cache the result in a field exposed via {@link #$cleanup()}. + */ default SwiftInstanceCleanup $createCleanup() { - return new JNISwiftInstanceCleanup( - $createDestroyFunction(), - $statusDestroyedFlag() - ); + return new JNISwiftInstanceCleanup($createDestroyFunction()); } } diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstanceCleanup.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstanceCleanup.java index 1dce368c..3719c3ad 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstanceCleanup.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/JNISwiftInstanceCleanup.java @@ -14,20 +14,29 @@ package org.swift.swiftkit.core; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; class JNISwiftInstanceCleanup implements SwiftInstanceCleanup { + private static final AtomicIntegerFieldUpdater DESTROYED = + AtomicIntegerFieldUpdater.newUpdater(JNISwiftInstanceCleanup.class, "destroyed"); + private final Runnable destroyFunction; - private final AtomicBoolean statusDestroyedFlag; - public JNISwiftInstanceCleanup(Runnable destroyFunction, AtomicBoolean statusDestroyedFlag) { + @SuppressWarnings("unused") // accessed via DESTROYED field updater + private volatile int destroyed; + + public JNISwiftInstanceCleanup(Runnable destroyFunction) { this.destroyFunction = destroyFunction; - this.statusDestroyedFlag = statusDestroyedFlag; + } + + @Override + public boolean isDestroyed() { + return destroyed != 0; } @Override public void run() { - if (statusDestroyedFlag.compareAndSet(false, true)) { + if (DESTROYED.compareAndSet(this, 0, 1)) { destroyFunction.run(); } else { throw new IllegalStateException("Double destruction attempt detected!"); diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java index 145af376..865a368e 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstance.java @@ -14,8 +14,6 @@ package org.swift.swiftkit.core; -import java.util.concurrent.atomic.AtomicBoolean; - public interface SwiftInstance { /** * Pointer to the {@code self} of the underlying Swift object or value. @@ -27,20 +25,16 @@ public interface SwiftInstance { long $memoryAddress(); /** - * Called when the arena has decided the value should be destroyed. + * Returns the cleanup associated with this instance. *

- * Warning: The cleanup action must not capture {@code this}. - */ - SwiftInstanceCleanup $createCleanup(); - - /** - * Exposes a boolean value which can be used to indicate if the object was destroyed. + * The same cleanup instance is returned on every call. The cleanup also serves as the + * destroyed-state holder, allowing callers to poll {@link SwiftInstanceCleanup#isDestroyed()} + * even after this instance has been GC-ed. *

- * This is exposing the object, rather than performing the action because we don't want to accidentally - * form a strong reference to the {@code SwiftInstance} which could prevent the cleanup from running, - * if using an GC managed instance (e.g. using an {@code AutoSwiftMemorySession}. + * Warning: The cleanup must not capture {@code this}. */ - AtomicBoolean $statusDestroyedFlag(); + SwiftInstanceCleanup $cleanup(); + /** * Ensures that this instance has not been destroyed. *

@@ -49,7 +43,7 @@ public interface SwiftInstance { * use-after-free errors. */ default void $ensureAlive() { - if (this.$statusDestroyedFlag().get()) { + if (this.$cleanup().isDestroyed()) { throw new IllegalStateException("Attempted to call method on already destroyed instance of " + getClass().getSimpleName() + "!"); } } diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstanceCleanup.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstanceCleanup.java index 56416968..54afe138 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstanceCleanup.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/SwiftInstanceCleanup.java @@ -16,5 +16,13 @@ /** * A Swift memory instance cleanup, e.g. count-down a reference count and destroy a class, or destroy struct/enum etc. + *

+ * Implementations also serve as the destroyed-state holder for their associated {@link SwiftInstance}, + * exposing {@link #isDestroyed()} which can be polled even after the instance has been GC-ed. */ -public interface SwiftInstanceCleanup extends Runnable {} \ No newline at end of file +public interface SwiftInstanceCleanup extends Runnable { + /** + * Whether this cleanup has run, i.e. the associated instance has been destroyed. + */ + boolean isDestroyed(); +} diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/collections/SwiftDictionaryMap.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/collections/SwiftDictionaryMap.java index 58489557..68f4d5c7 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/collections/SwiftDictionaryMap.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/collections/SwiftDictionaryMap.java @@ -15,7 +15,6 @@ package org.swift.swiftkit.core.collections; import java.util.*; -import java.util.concurrent.atomic.AtomicBoolean; import org.swift.swiftkit.core.*; @@ -33,10 +32,11 @@ public class SwiftDictionaryMap extends AbstractMap implements JNISwiftInstance { private final long selfPointer; - private final AtomicBoolean destroyed = new AtomicBoolean(false); + private final SwiftInstanceCleanup cleanup; private SwiftDictionaryMap(long selfPointer) { this.selfPointer = selfPointer; + this.cleanup = $createCleanup(); } public static SwiftDictionaryMap wrapMemoryAddressUnsafe(long selfPointer, SwiftArena arena) { @@ -58,8 +58,8 @@ public static SwiftDictionaryMap wrapMemoryAddressUnsafe(long selfP } @Override - public AtomicBoolean $statusDestroyedFlag() { - return destroyed; + public SwiftInstanceCleanup $cleanup() { + return cleanup; } @Override diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/collections/SwiftSet.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/collections/SwiftSet.java index 6779ba19..352c9358 100644 --- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/collections/SwiftSet.java +++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/collections/SwiftSet.java @@ -15,7 +15,6 @@ package org.swift.swiftkit.core.collections; import java.util.*; -import java.util.concurrent.atomic.AtomicBoolean; import org.swift.swiftkit.core.*; @@ -32,10 +31,11 @@ public class SwiftSet extends AbstractSet implements JNISwiftInstance { private final long selfPointer; - private final AtomicBoolean destroyed = new AtomicBoolean(false); + private final SwiftInstanceCleanup cleanup; private SwiftSet(long selfPointer) { this.selfPointer = selfPointer; + this.cleanup = $createCleanup(); } public static SwiftSet wrapMemoryAddressUnsafe(long selfPointer, SwiftArena arena) { @@ -57,8 +57,8 @@ public static SwiftSet wrapMemoryAddressUnsafe(long selfPointer, SwiftAre } @Override - public AtomicBoolean $statusDestroyedFlag() { - return destroyed; + public SwiftInstanceCleanup $cleanup() { + return cleanup; } @Override diff --git a/SwiftKitCore/src/test/java/org/swift/swiftkit/AutoArenaTest.java b/SwiftKitCore/src/test/java/org/swift/swiftkit/AutoArenaTest.java index 12093421..7dd1f3cd 100644 --- a/SwiftKitCore/src/test/java/org/swift/swiftkit/AutoArenaTest.java +++ b/SwiftKitCore/src/test/java/org/swift/swiftkit/AutoArenaTest.java @@ -17,8 +17,7 @@ import org.junit.jupiter.api.Test; import org.swift.swiftkit.core.JNISwiftInstance; import org.swift.swiftkit.core.SwiftArena; - -import java.util.concurrent.atomic.AtomicBoolean; +import org.swift.swiftkit.core.SwiftInstanceCleanup; public class AutoArenaTest { @@ -29,7 +28,7 @@ public void cleaner_releases_native_resource() { // This object is registered to the arena. var object = new FakeSwiftInstance(arena); - var statusDestroyedFlag = object.$statusDestroyedFlag(); + var cleanup = object.$cleanup(); // Release the object and hope it gets GC-ed soon @@ -37,7 +36,7 @@ public void cleaner_releases_native_resource() { object = null; var i = 1_000; - while (!statusDestroyedFlag.get()) { + while (!cleanup.isDestroyed()) { System.runFinalization(); System.gc(); @@ -48,9 +47,10 @@ public void cleaner_releases_native_resource() { } private static class FakeSwiftInstance implements JNISwiftInstance { - AtomicBoolean $state$destroyed = new AtomicBoolean(false); + private final SwiftInstanceCleanup cleanup; public FakeSwiftInstance(SwiftArena arena) { + this.cleanup = $createCleanup(); arena.register(this); } @@ -69,8 +69,8 @@ public FakeSwiftInstance(SwiftArena arena) { } @Override - public AtomicBoolean $statusDestroyedFlag() { - return $state$destroyed; + public SwiftInstanceCleanup $cleanup() { + return cleanup; } } } diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java index 7063fefb..f9fc8553 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/AllocatingAutoSwiftMemorySession.java @@ -56,7 +56,7 @@ public void register(SwiftInstance instance) { // We make sure we don't capture `instance` in the // cleanup action, so we can ignore the warning below. - var cleanupAction = instance.$createCleanup(); + var cleanupAction = instance.$cleanup(); cleaner.register(instance, cleanupAction); } diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftErrorInstance.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftErrorInstance.java index 224faaec..4fa41f3c 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftErrorInstance.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftErrorInstance.java @@ -18,7 +18,6 @@ import org.swift.swiftkit.core.SwiftInstanceCleanup; import java.lang.foreign.MemorySegment; -import java.util.concurrent.atomic.AtomicBoolean; /** * Base class for Swift errors passed across the FFM boundary. @@ -27,17 +26,19 @@ */ public abstract class FFMSwiftErrorInstance extends Exception implements SwiftInstance { private final MemorySegment memorySegment; - private final AtomicBoolean $state$destroyed = new AtomicBoolean(false); + private final FFMSwiftInstanceCleanup cleanup; protected FFMSwiftErrorInstance(String message, MemorySegment segment, AllocatingSwiftArena arena) { super(message); this.memorySegment = segment; + this.cleanup = new FFMSwiftInstanceCleanup(segment, $swiftType()); arena.register(this); } protected FFMSwiftErrorInstance(MemorySegment segment, AllocatingSwiftArena arena) { super(); this.memorySegment = segment; + this.cleanup = new FFMSwiftInstanceCleanup(segment, $swiftType()); arena.register(this); } @@ -50,21 +51,13 @@ protected FFMSwiftErrorInstance(MemorySegment segment, AllocatingSwiftArena aren return $memorySegment().address(); } - public final AtomicBoolean $statusDestroyedFlag() { - return $state$destroyed; + @Override + public final SwiftInstanceCleanup $cleanup() { + return this.cleanup; } /** * The Swift type metadata of this type. */ public abstract SwiftAnyType $swiftType(); - - @Override - public SwiftInstanceCleanup $createCleanup() { - return new FFMSwiftInstanceCleanup( - $memorySegment(), - $swiftType(), - $statusDestroyedFlag() - ); - } } diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java index bc8a2d9e..11476087 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstance.java @@ -18,14 +18,10 @@ import org.swift.swiftkit.core.SwiftInstanceCleanup; import java.lang.foreign.MemorySegment; -import java.util.concurrent.atomic.AtomicBoolean; public abstract class FFMSwiftInstance implements SwiftInstance { private final MemorySegment memorySegment; - - // TODO: make this a flagset integer and/or use a field updater - /** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */ - private final AtomicBoolean $state$destroyed = new AtomicBoolean(false); + private final FFMSwiftInstanceCleanup cleanup; /** * The designated constructor of any imported Swift types. @@ -35,6 +31,7 @@ public abstract class FFMSwiftInstance implements SwiftInstance { */ protected FFMSwiftInstance(MemorySegment segment, AllocatingSwiftArena arena) { this.memorySegment = segment; + this.cleanup = new FFMSwiftInstanceCleanup(segment, $swiftType()); // Only register once we have fully initialized the object since this will need the object pointer. arena.register(this); @@ -57,24 +54,9 @@ protected FFMSwiftInstance(MemorySegment segment, AllocatingSwiftArena arena) { */ public abstract SwiftAnyType $swiftType(); - /** - * Exposes a boolean value which can be used to indicate if the object was destroyed. - *

- * This is exposing the object, rather than performing the action because we don't want to accidentally - * form a strong reference to the {@code SwiftInstance} which could prevent the cleanup from running, - * if using an GC managed instance (e.g. using an {@code AutoSwiftMemorySession}. - */ - public final AtomicBoolean $statusDestroyedFlag() { - return this.$state$destroyed; - } - @Override - public SwiftInstanceCleanup $createCleanup() { - return new FFMSwiftInstanceCleanup( - $memorySegment(), - $swiftType(), - $statusDestroyedFlag() - ); + public final SwiftInstanceCleanup $cleanup() { + return this.cleanup; } /** diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java index 97c4808d..6f4f6e1e 100644 --- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java +++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/FFMSwiftInstanceCleanup.java @@ -19,22 +19,31 @@ import static org.swift.swiftkit.ffm.SwiftJavaLogGroup.LIFECYCLE; import java.lang.foreign.MemorySegment; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; + +class FFMSwiftInstanceCleanup implements SwiftInstanceCleanup { + private static final AtomicIntegerFieldUpdater DESTROYED = + AtomicIntegerFieldUpdater.newUpdater(FFMSwiftInstanceCleanup.class, "destroyed"); -public class FFMSwiftInstanceCleanup implements SwiftInstanceCleanup { private final MemorySegment memoryAddress; private final SwiftAnyType type; - private final AtomicBoolean statusDestroyedFlag; - public FFMSwiftInstanceCleanup(MemorySegment memoryAddress, SwiftAnyType type, AtomicBoolean statusDestroyedFlag) { + @SuppressWarnings("unused") // accessed via DESTROYED field updater + private volatile int destroyed; + + public FFMSwiftInstanceCleanup(MemorySegment memoryAddress, SwiftAnyType type) { this.memoryAddress = memoryAddress; this.type = type; - this.statusDestroyedFlag = statusDestroyedFlag; + } + + @Override + public boolean isDestroyed() { + return destroyed != 0; } @Override public void run() { - if (statusDestroyedFlag.compareAndSet(false, true)) { + if (DESTROYED.compareAndSet(this, 0, 1)) { // Allow null pointers just for AutoArena tests. if (type != null && memoryAddress != null) { SwiftRuntime.log(LIFECYCLE, "Destroy swift value [" + type.getSwiftName() + "]: " + memoryAddress); diff --git a/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/AutoArenaTest.java b/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/AutoArenaTest.java index 18c0a5af..024696ed 100644 --- a/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/AutoArenaTest.java +++ b/SwiftKitFFM/src/test/java/org/swift/swiftkit/ffm/AutoArenaTest.java @@ -16,9 +16,7 @@ import org.junit.jupiter.api.Test; -import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; -import java.util.concurrent.atomic.AtomicBoolean; public class AutoArenaTest { @@ -29,7 +27,7 @@ public void cleaner_releases_native_resource() { // This object is registered to the arena. var object = new FakeSwiftInstance(arena); - var statusDestroyedFlag = object.$statusDestroyedFlag(); + var cleanup = object.$cleanup(); // Release the object and hope it gets GC-ed soon @@ -37,7 +35,7 @@ public void cleaner_releases_native_resource() { object = null; var i = 1_000; - while (!statusDestroyedFlag.get()) { + while (!cleanup.isDestroyed()) { System.runFinalization(); System.gc(); diff --git a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift index 00d2b4bd..e2ac9830 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIClassTests.swift @@ -58,7 +58,6 @@ struct JNIClassTests { import org.swift.swiftkit.core.util.*; import org.swift.swiftkit.core.collections.*; import java.util.*; - import java.util.concurrent.atomic.AtomicBoolean; import org.swift.swiftkit.core.annotations.*; """, """ @@ -85,6 +84,7 @@ struct JNIClassTests { private MyClass(long selfPointer, SwiftArena swiftArena) { SwiftObjects.requireNonZero(selfPointer, "selfPointer"); this.selfPointer = selfPointer; + this.$cleanup = $createCleanup(); // Only register once we have fully initialized the object since this will need the object pointer. swiftArena.register(this); diff --git a/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift b/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift index 8c7a3714..5339e07d 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift @@ -46,7 +46,6 @@ struct JNIEnumTests { import org.swift.swiftkit.core.util.*; import org.swift.swiftkit.core.collections.*; import java.util.*; - import java.util.concurrent.atomic.AtomicBoolean; import org.swift.swiftkit.core.annotations.*; """, """ @@ -65,6 +64,7 @@ struct JNIEnumTests { private MyEnum(long selfPointer, SwiftArena swiftArena) { SwiftObjects.requireNonZero(selfPointer, "selfPointer"); this.selfPointer = selfPointer; + this.$cleanup = $createCleanup(); // Only register once we have fully initialized the object since this will need the object pointer. swiftArena.register(this); diff --git a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift index b0c3bfbb..8b63d982 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIModuleTests.swift @@ -53,7 +53,6 @@ struct JNIModuleTests { import org.swift.swiftkit.core.util.*; import org.swift.swiftkit.core.collections.*; import java.util.*; - import java.util.concurrent.atomic.AtomicBoolean; import org.swift.swiftkit.core.annotations.*; public final class SwiftModule { diff --git a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift index 8739a96a..c83c8af6 100644 --- a/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift +++ b/Tests/JExtractSwiftTests/JNI/JNIStructTests.swift @@ -71,6 +71,7 @@ struct JNIStructTests { private MyStruct(long selfPointer, SwiftArena swiftArena) { SwiftObjects.requireNonZero(selfPointer, "selfPointer"); this.selfPointer = selfPointer; + this.$cleanup = $createCleanup(); // Only register once we have fully initialized the object since this will need the object pointer. swiftArena.register(this);