FULL PRODUCT VERSION : java version "1.5.0_09" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_09-b03) Java HotSpot(TM) Client VM (build 1.5.0_09-b03, mixed mode, sharing) FULL OS VERSION : Microsoft Windows XP [Version 5.1.2600] A DESCRIPTION OF THE PROBLEM : SoftReferences are not being collected before OutOfMemoryError only when using the "-server" VM option, this does NOT happen using the client VM. This is a clear violation of the behavior laid out in the SoftReference.java javadoc: x * <p> All soft references to softly-reachable objects are guaranteed to have * been cleared before the virtual machine throws an * <code>OutOfMemoryError</code>. I believe this is the same issue seen in defect 4701459, but from what I read the fix for that defect never made it into code for some reason or another. The code to reproduce this might seem a bit contrived, but it quickly reproduces the same issue that is seen with our caching mechanism only when the "-server" vm option is enabled. The VM Params to use to reproduce the problem are: -Xmx1000m -Xms1000m -server THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: Yes THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Yes STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : 1. Run the main() of the attached code EXPECTED VERSUS ACTUAL BEHAVIOR : Expected: SoftReferences are GCed before an OOM Error Actual: SoftReferences are not GCed before an OOM Error for the java server VM, works as expected on the client VM ERROR MESSAGES/STACK TRACES THAT OCCUR : Exception in thread "main" java.lang.OutOfMemoryError: Java heap space REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- import java.lang.ref.SoftReference; import java.util.List; import java.util.ArrayList; public class SoftReferenceError { public static void main(String[] args) { List<SoftReference> data = new ArrayList<SoftReference>(); for(int i=0; i<80; i++){ data.add(new SoftReference(getStrVals(1300000))); System.out.println(i); System.out.println("Used Memory: " + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1000000d)); } } private static String[] getStrVals(int len){ String[] ret = new String[len]; for (int i = 0; i < len; i++) { ret[i] = getString(8); } return ret; } /** * A method that generates a string whos member data is not shared */ private static String getString(int num) { StringBuilder sb = new StringBuilder(num); for (int i = 0; i < num; i++) { sb.append(i); } return sb.toString(); } } ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : Use the client VM, not a very appealing solution for a large server app
|