Details
-
Bug
-
Resolution: Fixed
-
P4
-
8
-
b23
-
generic
-
generic
-
Verified
Backports
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8316589 | 17.0.10 | Sergey Chernyshev | P4 | Resolved | Fixed | b01 |
Description
FULL PRODUCT VERSION :
Issue exists since Java 1.5
ADDITIONAL OS VERSION INFORMATION :
All Platforms
A DESCRIPTION OF THE PROBLEM :
javax.crypto.JceSecurity holds a static map of all Provider instances ever inspected for code integrity. This leaks memory when Provider instances are continuously, created, used, and de-referenced in application code.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
In a tight loop, create a new Provider, do some operation with it that ensures verification, and then de-reference it in application code. This will eventually lead to an OutOfMemoryError.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No OutOfMemoryError
ACTUAL -
OutOfMemoryError
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.OutOfMemoryError: GC overhead limit exceeded
REPRODUCIBILITY :
This bug can be reproduced often.
---------- BEGIN SOURCE ----------
with Xmx=256m, this will throw an OutOfMemoryError:
for (int i = 0; i < 10000; i++) {
SunJCE jceProvider = new SunJCE();
Cipher c = Cipher.getInstance("AES", jceProvider);
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Map<Provider, Object> map = Collections.synchronizedMap(new WeakHashMap<>());
Class cl = Class.forName("javax.crypto.JceSecurity");
Field field = cl.getDeclaredField("verificationResults");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField( "modifiers" );
modifiersField.setAccessible( true );
modifiersField.setInt( field, field.getModifiers() & ~Modifier.FINAL );
Map<Provider, Object> verificationResults = (Map<Provider, Object>) field.get(null);
map.putAll(verificationResults);
field.set(null, map);
Issue exists since Java 1.5
ADDITIONAL OS VERSION INFORMATION :
All Platforms
A DESCRIPTION OF THE PROBLEM :
javax.crypto.JceSecurity holds a static map of all Provider instances ever inspected for code integrity. This leaks memory when Provider instances are continuously, created, used, and de-referenced in application code.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
In a tight loop, create a new Provider, do some operation with it that ensures verification, and then de-reference it in application code. This will eventually lead to an OutOfMemoryError.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No OutOfMemoryError
ACTUAL -
OutOfMemoryError
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.OutOfMemoryError: GC overhead limit exceeded
REPRODUCIBILITY :
This bug can be reproduced often.
---------- BEGIN SOURCE ----------
with Xmx=256m, this will throw an OutOfMemoryError:
for (int i = 0; i < 10000; i++) {
SunJCE jceProvider = new SunJCE();
Cipher c = Cipher.getInstance("AES", jceProvider);
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Map<Provider, Object> map = Collections.synchronizedMap(new WeakHashMap<>());
Class cl = Class.forName("javax.crypto.JceSecurity");
Field field = cl.getDeclaredField("verificationResults");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField( "modifiers" );
modifiersField.setAccessible( true );
modifiersField.setInt( field, field.getModifiers() & ~Modifier.FINAL );
Map<Provider, Object> verificationResults = (Map<Provider, Object>) field.get(null);
map.putAll(verificationResults);
field.set(null, map);
Attachments
Issue Links
- backported by
-
JDK-8316589 Memory leak in JceSecurity
- Resolved