FULL PRODUCT VERSION :
java version "1.6.0_17"
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]
A DESCRIPTION OF THE PROBLEM :
Date's before and after methods call getMillisOf(), which will clone the cdate variable if not-null. NB: cdate is not null after a simple call to toString(), for instance for logging purposes.
On the other hand getTime() does not incurr the cloning penalty. So rewriting
a.before(b) to a.getTime() < b.getTime() uses less memory, which is sad. The semantically string before/after should not be more expensive than a verbose getTime() construct.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Have an application relying a lot on before() and after()
2. Perform logging that calls toString() on the date instances
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
before() and after() should not perform any object allocation.
ACTUAL -
before() and after() clone the internal BaseCalendar.Date.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.util.Date;
public class BeforeTest {
public static void main(String[] args) {
int n = 100000;
Runtime rt = Runtime.getRuntime();
Date a = new Date();
a.toString();
Date b = new Date();
b.toString();
long mem1 = rt.totalMemory() - rt.freeMemory();
for (int i=0; i<n; i++) {
if (a.getTime() < b.getTime()) continue;
}
long mem2 = rt.totalMemory() - rt.freeMemory();
System.out.println("with getTime(): "+ (mem2 - mem1));
mem1 = rt.totalMemory() - rt.freeMemory();
for (int i=0; i<n; i++) {
if (a.before(b)) continue;
}
mem2 = rt.totalMemory() - rt.freeMemory();
System.gc();
System.out.println("with before(): "+ (mem2 - mem1));
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Use getTime() instead of before() or after().