Skip to content

Commit aba3431

Browse files
committed
8258956: Memory Leak in StringCoding on ThreadLocal resultCached StringCoding.Result
Reviewed-by: rriggs, alanb
1 parent 8554fe6 commit aba3431

File tree

1 file changed

+18
-9
lines changed

1 file changed

+18
-9
lines changed

src/java.base/share/classes/java/lang/StringCoding.java

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -523,16 +523,25 @@ static byte[] encode(byte coder, byte[] val) {
523523
private static native void err(String msg);
524524

525525
/* The cached Result for each thread */
526-
private static final ThreadLocal<StringCoding.Result>
526+
private static final ThreadLocal<SoftReference<Result>>
527527
resultCached = new ThreadLocal<>() {
528-
protected StringCoding.Result initialValue() {
529-
return new StringCoding.Result();
528+
protected SoftReference<Result> initialValue() {
529+
return new SoftReference<>(new Result());
530530
}};
531+
private static Result resultCached() {
532+
SoftReference<Result> sr = resultCached.get();
533+
Result r;
534+
if (sr == null || (r = sr.get()) == null) {
535+
r = new Result();
536+
resultCached.set(new SoftReference<>(r));
537+
}
538+
return r;
539+
}
531540

532541
////////////////////////// ascii //////////////////////////////
533542

534543
private static Result decodeASCII(byte[] ba, int off, int len) {
535-
Result result = resultCached.get();
544+
Result result = resultCached();
536545
if (COMPACT_STRINGS && !hasNegatives(ba, off, len)) {
537546
return result.with(Arrays.copyOfRange(ba, off, off + len),
538547
LATIN1);
@@ -582,7 +591,7 @@ private static byte[] encodeASCII(byte coder, byte[] val) {
582591
////////////////////////// latin1/8859_1 ///////////////////////////
583592

584593
private static Result decodeLatin1(byte[] ba, int off, int len) {
585-
Result result = resultCached.get();
594+
Result result = resultCached();
586595
if (COMPACT_STRINGS) {
587596
return result.with(Arrays.copyOfRange(ba, off, off + len), LATIN1);
588597
} else {
@@ -720,13 +729,13 @@ private static void throwUnmappable(byte[] val) {
720729
private static Result decodeUTF8(byte[] src, int sp, int len, boolean doReplace) {
721730
// ascii-bais, which has a relative impact to the non-ascii-only bytes
722731
if (COMPACT_STRINGS && !hasNegatives(src, sp, len))
723-
return resultCached.get().with(Arrays.copyOfRange(src, sp, sp + len),
732+
return resultCached().with(Arrays.copyOfRange(src, sp, sp + len),
724733
LATIN1);
725734
return decodeUTF8_0(src, sp, len, doReplace);
726735
}
727736

728737
private static Result decodeUTF8_0(byte[] src, int sp, int len, boolean doReplace) {
729-
Result ret = resultCached.get();
738+
Result ret = resultCached();
730739

731740
int sl = sp + len;
732741
int dp = 0;
@@ -1057,7 +1066,7 @@ static String newStringNoRepl1(byte[] src, Charset cs) {
10571066
} catch (CharacterCodingException x) {
10581067
throw new IllegalArgumentException(x); // todo
10591068
}
1060-
Result ret = resultCached.get().with(ca, 0, cb.position());
1069+
Result ret = resultCached().with(ca, 0, cb.position());
10611070
return new String(ret.value, ret.coder);
10621071
}
10631072

0 commit comments

Comments
 (0)