Attempt to fix NestedJarFile file lock issues on Windows
Update `DefaultCleanerTracking` and `@AssertFileChannelDataBlocksClosed` to capture and store the source object if it is a `Cleanable` so that it can be released later. Although the real cleaner cannot keep a reference to `obj`, it is safe for us to do so in tests since we are in control of the object lifecycle and we don't need it to be garbage collected. This commit also updates the `UrlJarFile` to call the cleaner so that it can be tracked. See gh-37668
This commit is contained in:
@@ -24,6 +24,8 @@ import java.util.jar.Manifest;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import org.springframework.boot.loader.ref.Cleaner;
|
||||
|
||||
/**
|
||||
* A {@link JarFile} subclass returned from a {@link JarUrlConnection}.
|
||||
*
|
||||
@@ -37,6 +39,8 @@ class UrlJarFile extends JarFile {
|
||||
|
||||
UrlJarFile(File file, Runtime.Version version, Consumer<JarFile> closeAction) throws IOException {
|
||||
super(file, true, ZipFile.OPEN_READ, version);
|
||||
// Registered only for test cleanup since parent class is JarFile
|
||||
Cleaner.instance.register(this, null);
|
||||
this.manifest = new UrlJarManifest(super::getManifest);
|
||||
this.closeAction = closeAction;
|
||||
}
|
||||
@@ -53,7 +57,9 @@ class UrlJarFile extends JarFile {
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
this.closeAction.accept(this);
|
||||
if (this.closeAction != null) {
|
||||
this.closeAction.accept(this);
|
||||
}
|
||||
super.close();
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,9 @@ class UrlNestedJarFile extends NestedJarFile {
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
this.closeAction.accept(this);
|
||||
if (this.closeAction != null) {
|
||||
this.closeAction.accept(this);
|
||||
}
|
||||
super.close();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package org.springframework.boot.loader.ref;
|
||||
|
||||
import java.lang.ref.Cleaner.Cleanable;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
* Default {@link Cleaner} implementation that delegates to {@link java.lang.ref.Cleaner}.
|
||||
@@ -28,15 +28,15 @@ class DefaultCleaner implements Cleaner {
|
||||
|
||||
static final DefaultCleaner instance = new DefaultCleaner();
|
||||
|
||||
static Consumer<Cleanable> tracker;
|
||||
static BiConsumer<Object, Cleanable> tracker;
|
||||
|
||||
private final java.lang.ref.Cleaner cleaner = java.lang.ref.Cleaner.create();
|
||||
|
||||
@Override
|
||||
public Cleanable register(Object obj, Runnable action) {
|
||||
Cleanable cleanable = this.cleaner.register(obj, action);
|
||||
Cleanable cleanable = (action != null) ? this.cleaner.register(obj, action) : null;
|
||||
if (tracker != null) {
|
||||
tracker.accept(cleanable);
|
||||
tracker.accept(obj, cleanable);
|
||||
}
|
||||
return cleanable;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user