Skip to content

Commit b897fc2

Browse files
author
redestad
committed
8193507: [REDO] Startup regression due to JDK-8185582
Reviewed-by: alanb, rriggs Contributed-by: [email protected], [email protected]
1 parent 8b32eb0 commit b897fc2

File tree

4 files changed

+170
-121
lines changed

4 files changed

+170
-121
lines changed

src/java.base/share/classes/java/util/zip/Deflater.java

+77-4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525

2626
package java.util.zip;
2727

28+
import java.lang.ref.Cleaner.Cleanable;
29+
import jdk.internal.ref.CleanerFactory;
30+
2831
/**
2932
* This class provides support for general purpose compression using the
3033
* popular ZLIB compression library. The ZLIB compression library was
@@ -88,7 +91,7 @@
8891

8992
public class Deflater {
9093

91-
private final ZStreamRef zsRef;
94+
private final DeflaterZStreamRef zsRef;
9295
private byte[] buf = new byte[0];
9396
private int off, len;
9497
private int level, strategy;
@@ -183,9 +186,8 @@ public class Deflater {
183186
public Deflater(int level, boolean nowrap) {
184187
this.level = level;
185188
this.strategy = DEFAULT_STRATEGY;
186-
this.zsRef = ZStreamRef.get(this,
187-
() -> init(level, DEFAULT_STRATEGY, nowrap),
188-
Deflater::end);
189+
this.zsRef = DeflaterZStreamRef.get(this,
190+
init(level, DEFAULT_STRATEGY, nowrap));
189191
}
190192

191193
/**
@@ -591,4 +593,75 @@ private native int deflateBytes(long addr, byte[] b, int off, int len,
591593
private static native int getAdler(long addr);
592594
private static native void reset(long addr);
593595
private static native void end(long addr);
596+
597+
/**
598+
* A reference to the native zlib's z_stream structure. It also
599+
* serves as the "cleaner" to clean up the native resource when
600+
* the Deflater is ended, closed or cleaned.
601+
*/
602+
static class DeflaterZStreamRef implements Runnable {
603+
604+
private long address;
605+
private final Cleanable cleanable;
606+
607+
private DeflaterZStreamRef(Deflater owner, long addr) {
608+
this.cleanable = (owner != null) ? CleanerFactory.cleaner().register(owner, this) : null;
609+
this.address = addr;
610+
}
611+
612+
long address() {
613+
return address;
614+
}
615+
616+
void clean() {
617+
cleanable.clean();
618+
}
619+
620+
public synchronized void run() {
621+
long addr = address;
622+
address = 0;
623+
if (addr != 0) {
624+
end(addr);
625+
}
626+
}
627+
628+
/*
629+
* If {@code Deflater} has been subclassed and the {@code end} method is
630+
* overridden, uses {@code finalizer} mechanism for resource cleanup. So
631+
* {@code end} method can be called when the {@code Deflater} is unreachable.
632+
* This mechanism will be removed when the {@code finalize} method is
633+
* removed from {@code Deflater}.
634+
*/
635+
static DeflaterZStreamRef get(Deflater owner, long addr) {
636+
Class<?> clz = owner.getClass();
637+
while (clz != Deflater.class) {
638+
try {
639+
clz.getDeclaredMethod("end");
640+
return new FinalizableZStreamRef(owner, addr);
641+
} catch (NoSuchMethodException nsme) {}
642+
clz = clz.getSuperclass();
643+
}
644+
return new DeflaterZStreamRef(owner, addr);
645+
}
646+
647+
private static class FinalizableZStreamRef extends DeflaterZStreamRef {
648+
final Deflater owner;
649+
650+
FinalizableZStreamRef (Deflater owner, long addr) {
651+
super(null, addr);
652+
this.owner = owner;
653+
}
654+
655+
@Override
656+
void clean() {
657+
run();
658+
}
659+
660+
@Override
661+
@SuppressWarnings("deprecation")
662+
protected void finalize() {
663+
owner.end();
664+
}
665+
}
666+
}
594667
}

src/java.base/share/classes/java/util/zip/Inflater.java

+76-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525

2626
package java.util.zip;
2727

28+
import java.lang.ref.Cleaner.Cleanable;
29+
import jdk.internal.ref.CleanerFactory;
30+
2831
/**
2932
* This class provides support for general purpose decompression using the
3033
* popular ZLIB compression library. The ZLIB compression library was
@@ -88,7 +91,7 @@
8891

8992
public class Inflater {
9093

91-
private final ZStreamRef zsRef;
94+
private final InflaterZStreamRef zsRef;
9295
private byte[] buf = defaultBuf;
9396
private int off, len;
9497
private boolean finished;
@@ -115,7 +118,7 @@ public class Inflater {
115118
* @param nowrap if true then support GZIP compatible compression
116119
*/
117120
public Inflater(boolean nowrap) {
118-
this.zsRef = ZStreamRef.get(this, () -> init(nowrap), Inflater::end);
121+
this.zsRef = InflaterZStreamRef.get(this, init(nowrap));
119122
}
120123

121124
/**
@@ -428,4 +431,75 @@ private native int inflateBytes(long addr, byte[] b, int off, int len)
428431
private static native int getAdler(long addr);
429432
private static native void reset(long addr);
430433
private static native void end(long addr);
434+
435+
/**
436+
* A reference to the native zlib's z_stream structure. It also
437+
* serves as the "cleaner" to clean up the native resource when
438+
* the Inflater is ended, closed or cleaned.
439+
*/
440+
static class InflaterZStreamRef implements Runnable {
441+
442+
private long address;
443+
private final Cleanable cleanable;
444+
445+
private InflaterZStreamRef(Inflater owner, long addr) {
446+
this.cleanable = (owner != null) ? CleanerFactory.cleaner().register(owner, this) : null;
447+
this.address = addr;
448+
}
449+
450+
long address() {
451+
return address;
452+
}
453+
454+
void clean() {
455+
cleanable.clean();
456+
}
457+
458+
public synchronized void run() {
459+
long addr = address;
460+
address = 0;
461+
if (addr != 0) {
462+
end(addr);
463+
}
464+
}
465+
466+
/*
467+
* If {@code Inflater} has been subclassed and the {@code end} method is
468+
* overridden, uses {@code finalizer} mechanism for resource cleanup. So
469+
* {@code end} method can be called when the {@code Inflater} is unreachable.
470+
* This mechanism will be removed when the {@code finalize} method is
471+
* removed from {@code Inflater}.
472+
*/
473+
static InflaterZStreamRef get(Inflater owner, long addr) {
474+
Class<?> clz = owner.getClass();
475+
while (clz != Inflater.class) {
476+
try {
477+
clz.getDeclaredMethod("end");
478+
return new FinalizableZStreamRef(owner, addr);
479+
} catch (NoSuchMethodException nsme) {}
480+
clz = clz.getSuperclass();
481+
}
482+
return new InflaterZStreamRef(owner, addr);
483+
}
484+
485+
private static class FinalizableZStreamRef extends InflaterZStreamRef {
486+
final Inflater owner;
487+
488+
FinalizableZStreamRef(Inflater owner, long addr) {
489+
super(null, addr);
490+
this.owner = owner;
491+
}
492+
493+
@Override
494+
void clean() {
495+
run();
496+
}
497+
498+
@Override
499+
@SuppressWarnings("deprecation")
500+
protected void finalize() {
501+
owner.end();
502+
}
503+
}
504+
}
431505
}

src/java.base/share/classes/java/util/zip/ZStreamRef.java

-113
This file was deleted.

src/java.base/share/classes/java/util/zip/ZipFile.java

+17-2
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,21 @@ public InputStream getInputStream(ZipEntry entry) throws IOException {
412412
}
413413
}
414414

415+
private static class InflaterCleanupAction implements Runnable {
416+
private final Inflater inf;
417+
private final CleanableResource res;
418+
419+
InflaterCleanupAction(Inflater inf, CleanableResource res) {
420+
this.inf = inf;
421+
this.res = res;
422+
}
423+
424+
@Override
425+
public void run() {
426+
res.releaseInflater(inf);
427+
}
428+
}
429+
415430
private class ZipFileInflaterInputStream extends InflaterInputStream {
416431
private volatile boolean closeRequested;
417432
private boolean eof = false;
@@ -427,8 +442,8 @@ private ZipFileInflaterInputStream(ZipFileInputStream zfin,
427442
Inflater inf, int size) {
428443
super(zfin, inf, size);
429444
this.cleanable = CleanerFactory.cleaner().register(this,
430-
() -> res.releaseInflater(inf));
431-
}
445+
new InflaterCleanupAction(inf, res));
446+
}
432447

433448
public void close() throws IOException {
434449
if (closeRequested)

0 commit comments

Comments
 (0)