Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-2172154 | 7 | Joe Wang | P3 | Closed | Fixed | m05 |
JDK-2173285 | 6u14 | Abhijit Saha | P2 | Resolved | Fixed | b02 |
JDK-2173507 | 1.4.0 | Joe Wang | P2 | Closed | Fixed | 1.4 |
During memory analysis, we found high transient memory usage (8MB)
in the Catalog.normalizeURI usage of StringBuilder.append:
4.5% - 7,841 kB - 57,052 alloc.
com.sun.org.apache.xml.internal.resolver.Catalog.resolveSystem
4.4% - 7,735 kB - 56,164 alloc.
com.sun.org.apache.xml.internal.resolver.Catalog.normalizeURI
1.9% - 3,253 kB - 7,486 alloc. java.lang.StringBuilder.append(char)
1.0% - 1,765 kB - 8,670 alloc.
java.lang.StringBuilder.append(java.lang.String)
3.2% - 5,626 kB - 45,912 alloc.
com.sun.org.apache.xml.internal.resolver.Catalog.resolvePublic
3.1% - 5,507 kB - 44,460 alloc.
com.sun.org.apache.xml.internal.resolver.Catalog.normalizeURI
1.3% - 2,255 kB - 5,738 alloc. java.lang.StringBuilder.append(char)
0.7% - 1,245 kB - 6,794 alloc.
java.lang.StringBuilder.append(java.lang.String)
The culprit is the following for loop that creates new StringBuilder instances with 0 size, so that each call to append creates a new StringBuilder instance, leaving the
old one on the heap, hence the high transient memory usage.
for(int count = 0; count < bytes.length; count++)
{
int ch = bytes[count] & 0xff;
if(ch <= 32 || ch > 127 || ch == 34 || ch == 60 || ch == 62 || ch
== 92 || ch == 94 || ch == 96 || ch == 123 || ch == 124 || ch == 125 || ch ==
127)
newRef = (new
StringBuilder()).append(newRef).append(encodedByte(ch)).toString();
else
newRef = (new
StringBuilder()).append(newRef).append((char)bytes[count]).toString();
}
Recommendation:
1. create StringBuilder with estimated capacity before the for loop
StringBuilder sb = new StringBuilder(bytes.length);
for(int count = 0; count < bytes.length; count++)
{
int ch = bytes[count] & 0xff;
if(ch <= 32 || ch > 127 || ch == 34 || ch == 60 || ch == 62 || ch
== 92 || ch == 94 || ch == 96 || ch == 123 || ch == 124 || ch == 125 || ch ==
127)
newRef =
sb.append(newRef).append(encodedByte(ch)).toString();
else
newRef =
sb.append(newRef).append((char)bytes[count]).toString();
}
in the Catalog.normalizeURI usage of StringBuilder.append:
4.5% - 7,841 kB - 57,052 alloc.
com.sun.org.apache.xml.internal.resolver.Catalog.resolveSystem
4.4% - 7,735 kB - 56,164 alloc.
com.sun.org.apache.xml.internal.resolver.Catalog.normalizeURI
1.9% - 3,253 kB - 7,486 alloc. java.lang.StringBuilder.append(char)
1.0% - 1,765 kB - 8,670 alloc.
java.lang.StringBuilder.append(java.lang.String)
3.2% - 5,626 kB - 45,912 alloc.
com.sun.org.apache.xml.internal.resolver.Catalog.resolvePublic
3.1% - 5,507 kB - 44,460 alloc.
com.sun.org.apache.xml.internal.resolver.Catalog.normalizeURI
1.3% - 2,255 kB - 5,738 alloc. java.lang.StringBuilder.append(char)
0.7% - 1,245 kB - 6,794 alloc.
java.lang.StringBuilder.append(java.lang.String)
The culprit is the following for loop that creates new StringBuilder instances with 0 size, so that each call to append creates a new StringBuilder instance, leaving the
old one on the heap, hence the high transient memory usage.
for(int count = 0; count < bytes.length; count++)
{
int ch = bytes[count] & 0xff;
if(ch <= 32 || ch > 127 || ch == 34 || ch == 60 || ch == 62 || ch
== 92 || ch == 94 || ch == 96 || ch == 123 || ch == 124 || ch == 125 || ch ==
127)
newRef = (new
StringBuilder()).append(newRef).append(encodedByte(ch)).toString();
else
newRef = (new
StringBuilder()).append(newRef).append((char)bytes[count]).toString();
}
Recommendation:
1. create StringBuilder with estimated capacity before the for loop
StringBuilder sb = new StringBuilder(bytes.length);
for(int count = 0; count < bytes.length; count++)
{
int ch = bytes[count] & 0xff;
if(ch <= 32 || ch > 127 || ch == 34 || ch == 60 || ch == 62 || ch
== 92 || ch == 94 || ch == 96 || ch == 123 || ch == 124 || ch == 125 || ch ==
127)
newRef =
sb.append(newRef).append(encodedByte(ch)).toString();
else
newRef =
sb.append(newRef).append((char)bytes[count]).toString();
}
- backported by
-
JDK-2173285 Catalog resolver transient memory usage high
-
- Resolved
-
-
JDK-2173507 Catalog resolver transient memory usage high
-
- Closed
-
-
JDK-2172154 Catalog resolver transient memory usage high
-
- Closed
-