Skip to content

Commit 834db30

Browse files
committed
Share 'cleaned' reference across slices, do not call close() in finalization
1 parent ee872a3 commit 834db30

File tree

4 files changed

+26
-40
lines changed

4 files changed

+26
-40
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>software.coley</groupId>
88
<artifactId>lljzip</artifactId>
9-
<version>1.3.2</version>
9+
<version>1.3.3</version>
1010

1111
<name>LL Java ZIP</name>
1212
<description>Lower level ZIP support for Java</description>

src/main/java/software/coley/llzip/util/BufferData.java

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.nio.Buffer;
66
import java.nio.ByteBuffer;
77
import java.nio.ByteOrder;
8+
import java.util.concurrent.atomic.AtomicBoolean;
89

910
/**
1011
* File that is backed by a byte buffer.
@@ -13,10 +14,11 @@
1314
*/
1415
public final class BufferData implements ByteData {
1516
private final ByteBuffer buffer;
16-
private volatile boolean cleaned;
17+
private final AtomicBoolean cleaned;
1718

18-
private BufferData(ByteBuffer buffer) {
19+
private BufferData(ByteBuffer buffer, AtomicBoolean cleaned) {
1920
this.buffer = buffer;
21+
this.cleaned = cleaned;
2022
}
2123

2224
@Override
@@ -43,8 +45,7 @@ public void get(long position, byte[] b, int off, int len) {
4345
ensureOpen();
4446
// Left intentionally as unchained calls due to API differences across Java versions
4547
// and how the compiler changes output.
46-
ByteBuffer buffer = this.buffer;
47-
buffer.slice();
48+
ByteBuffer buffer = this.buffer.slice();
4849
buffer.order(buffer.order());
4950
((Buffer) buffer).position(validate(position));
5051
buffer.get(b, off, len);
@@ -73,7 +74,7 @@ public void transferTo(OutputStream out, byte[] buf) throws IOException {
7374
@Override
7475
public ByteData slice(long startIndex, long endIndex) {
7576
ensureOpen();
76-
return new BufferData(ByteDataUtil.sliceExact(buffer, validate(startIndex), validate(endIndex)));
77+
return new BufferData(ByteDataUtil.sliceExact(buffer, validate(startIndex), validate(endIndex)), cleaned);
7778
}
7879

7980
@Override
@@ -97,11 +98,11 @@ public int hashCode() {
9798

9899
@Override
99100
public void close() {
100-
if (!cleaned) {
101+
if (!cleaned.get()) {
101102
synchronized (this) {
102-
if (cleaned)
103+
if (cleaned.get())
103104
return;
104-
cleaned = true;
105+
cleaned.set(true);
105106
ByteBuffer buffer = this.buffer;
106107
if (buffer.isDirect()) {
107108
CleanerUtil.invokeCleaner(buffer);
@@ -110,17 +111,8 @@ public void close() {
110111
}
111112
}
112113

113-
@Override
114-
protected void finalize() throws Throwable {
115-
try {
116-
close();
117-
} finally {
118-
super.finalize();
119-
}
120-
}
121-
122114
private void ensureOpen() {
123-
if (cleaned)
115+
if (cleaned.get())
124116
throw new IllegalStateException("Cannot access data after close");
125117
}
126118

@@ -138,7 +130,7 @@ private static int validate(long v) {
138130
* @return Buffer data.
139131
*/
140132
public static BufferData wrap(ByteBuffer buffer) {
141-
return new BufferData(buffer);
133+
return new BufferData(buffer, new AtomicBoolean());
142134
}
143135

144136
/**
@@ -148,6 +140,6 @@ public static BufferData wrap(ByteBuffer buffer) {
148140
* @return Buffer data.
149141
*/
150142
public static BufferData wrap(byte[] array) {
151-
return new BufferData(ByteBuffer.wrap(array).order(ByteOrder.LITTLE_ENDIAN));
143+
return new BufferData(ByteBuffer.wrap(array).order(ByteOrder.LITTLE_ENDIAN), new AtomicBoolean());
152144
}
153145
}

src/main/java/software/coley/llzip/util/FileMapUtil.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.nio.file.Files;
1010
import java.nio.file.Path;
1111
import java.nio.file.StandardOpenOption;
12+
import java.util.concurrent.atomic.AtomicBoolean;
1213

1314
/**
1415
* Maps large files into memory.
@@ -65,7 +66,7 @@ public static ByteData map(Path path) throws IOException {
6566
} catch (IllegalAccessException | InvocationTargetException ex) {
6667
throw new InternalError(ex);
6768
}
68-
});
69+
}, new AtomicBoolean());
6970
return mappedFile;
7071
}
7172
}

src/main/java/software/coley/llzip/util/UnsafeMappedFile.java

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.io.IOException;
66
import java.io.OutputStream;
77
import java.nio.ByteOrder;
8+
import java.util.concurrent.atomic.AtomicBoolean;
89

910
/**
1011
* Mapped file backed by address & length.
@@ -15,24 +16,26 @@ final class UnsafeMappedFile implements ByteData {
1516
private static final boolean SWAP = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
1617
private static final Unsafe UNSAFE = UnsafeUtil.get();
1718

18-
private volatile boolean cleaned;
19+
private final AtomicBoolean cleaned;
1920
private final long address;
2021
private final long end;
2122
private final Runnable deallocator;
2223
@SuppressWarnings("unused")
2324
private final Object attachment;
2425

25-
private UnsafeMappedFile(Object attachment, long address, long end) {
26+
private UnsafeMappedFile(Object attachment, long address, long end, AtomicBoolean cleaned) {
2627
this.attachment = attachment;
2728
this.address = address;
2829
this.end = end;
30+
this.cleaned = cleaned;
2931
deallocator = null;
3032
}
3133

32-
UnsafeMappedFile(long address, long length, Runnable deallocator) {
34+
UnsafeMappedFile(long address, long length, Runnable deallocator, AtomicBoolean cleaned) {
3335
this.address = address;
3436
this.end = address + length;
3537
this.deallocator = deallocator;
38+
this.cleaned = cleaned;
3639
attachment = null;
3740
}
3841

@@ -83,7 +86,7 @@ public ByteData slice(long startIndex, long endIndex) {
8386
ensureOpen();
8487
if (startIndex > endIndex)
8588
throw new IllegalArgumentException();
86-
return new UnsafeMappedFile(this, validate(startIndex), validate(endIndex));
89+
return new UnsafeMappedFile(this, validate(startIndex), validate(endIndex), cleaned);
8790
}
8891

8992
@Override
@@ -113,11 +116,11 @@ public int hashCode() {
113116

114117
@Override
115118
public void close() {
116-
if (!cleaned) {
119+
if (!cleaned.get()) {
117120
synchronized (this) {
118-
if (cleaned)
121+
if (cleaned.get())
119122
return;
120-
cleaned = true;
123+
cleaned.set(true);
121124
Runnable deallocator = this.deallocator;
122125
if (deallocator != null)
123126
deallocator.run();
@@ -126,20 +129,10 @@ public void close() {
126129
}
127130

128131
private void ensureOpen() {
129-
if (cleaned)
132+
if (cleaned.get())
130133
throw new IllegalStateException("Cannot access data after close");
131134
}
132135

133-
@SuppressWarnings("deprecation")
134-
@Override
135-
protected void finalize() throws Throwable {
136-
try {
137-
close();
138-
} finally {
139-
super.finalize();
140-
}
141-
}
142-
143136
private long validate(long position) {
144137
if (position < 0L) {
145138
throw new IllegalArgumentException();

0 commit comments

Comments
 (0)