提交 0b740e68 authored 作者: Thomas Mueller's avatar Thomas Mueller

Issue 603: there was a memory leak when using H2 in a web application. Apache…

Issue 603: there was a memory leak when using H2 in a web application. Apache Tomcat logged an error message: "The web application ... created a ThreadLocal with key of type [org.h2.util.DateTimeUtils$1]".
上级 7387be71
...@@ -51,13 +51,15 @@ public class DateTimeUtils { ...@@ -51,13 +51,15 @@ public class DateTimeUtils {
private static final int[] DAYS_OFFSET = { 0, 31, 61, 92, 122, 153, 184, private static final int[] DAYS_OFFSET = { 0, 31, 61, 92, 122, 153, 184,
214, 245, 275, 306, 337, 366 }; 214, 245, 275, 306, 337, 366 };
private static final ThreadLocal<Calendar> CACHED_CALENDAR = /**
new ThreadLocal<Calendar>() { * The thread local. Can not override initialValue because this would result
@Override * in an inner class, which would not be garbage collected in a web
protected Calendar initialValue() { * container, and prevent the class loader of H2 from being garbage
return Calendar.getInstance(); * collected. Using a ThreadLocal on a system class like Calendar does have
} * that problem, and while it is still a small memory leak, it is not a
}; * class loader memory leak.
*/
private static final ThreadLocal<Calendar> CACHED_CALENDAR = new ThreadLocal<Calendar>();
private DateTimeUtils() { private DateTimeUtils() {
// utility class // utility class
...@@ -70,6 +72,15 @@ public class DateTimeUtils { ...@@ -70,6 +72,15 @@ public class DateTimeUtils {
CACHED_CALENDAR.remove(); CACHED_CALENDAR.remove();
} }
private static Calendar getCalendar() {
Calendar c = CACHED_CALENDAR.get();
if (c == null) {
c = Calendar.getInstance();
CACHED_CALENDAR.set(c);
}
return c;
}
/** /**
* Convert the date to the specified time zone. * Convert the date to the specified time zone.
* *
...@@ -380,7 +391,7 @@ public class DateTimeUtils { ...@@ -380,7 +391,7 @@ public class DateTimeUtils {
int millis) { int millis) {
Calendar c; Calendar c;
if (tz == null) { if (tz == null) {
c = CACHED_CALENDAR.get(); c = getCalendar();
} else { } else {
c = Calendar.getInstance(tz); c = Calendar.getInstance(tz);
} }
...@@ -417,7 +428,7 @@ public class DateTimeUtils { ...@@ -417,7 +428,7 @@ public class DateTimeUtils {
* @return the value * @return the value
*/ */
public static int getDatePart(java.util.Date d, int field) { public static int getDatePart(java.util.Date d, int field) {
Calendar c = CACHED_CALENDAR.get(); Calendar c = getCalendar();
c.setTime(d); c.setTime(d);
if (field == Calendar.YEAR) { if (field == Calendar.YEAR) {
return getYear(c); return getYear(c);
...@@ -451,7 +462,7 @@ public class DateTimeUtils { ...@@ -451,7 +462,7 @@ public class DateTimeUtils {
* @return the milliseconds * @return the milliseconds
*/ */
public static long getTimeLocalWithoutDst(java.util.Date d) { public static long getTimeLocalWithoutDst(java.util.Date d) {
return d.getTime() + CACHED_CALENDAR.get().get(Calendar.ZONE_OFFSET); return d.getTime() + getCalendar().get(Calendar.ZONE_OFFSET);
} }
/** /**
...@@ -462,7 +473,7 @@ public class DateTimeUtils { ...@@ -462,7 +473,7 @@ public class DateTimeUtils {
* @return the number of milliseconds in UTC * @return the number of milliseconds in UTC
*/ */
public static long getTimeUTCWithoutDst(long millis) { public static long getTimeUTCWithoutDst(long millis) {
return millis - CACHED_CALENDAR.get().get(Calendar.ZONE_OFFSET); return millis - getCalendar().get(Calendar.ZONE_OFFSET);
} }
/** /**
...@@ -732,7 +743,7 @@ public class DateTimeUtils { ...@@ -732,7 +743,7 @@ public class DateTimeUtils {
* @return the date value * @return the date value
*/ */
public static long dateValueFromDate(long ms) { public static long dateValueFromDate(long ms) {
Calendar cal = CACHED_CALENDAR.get(); Calendar cal = getCalendar();
cal.clear(); cal.clear();
cal.setTimeInMillis(ms); cal.setTimeInMillis(ms);
return dateValueFromCalendar(cal); return dateValueFromCalendar(cal);
...@@ -760,7 +771,7 @@ public class DateTimeUtils { ...@@ -760,7 +771,7 @@ public class DateTimeUtils {
* @return the nanoseconds * @return the nanoseconds
*/ */
public static long nanosFromDate(long ms) { public static long nanosFromDate(long ms) {
Calendar cal = CACHED_CALENDAR.get(); Calendar cal = getCalendar();
cal.clear(); cal.clear();
cal.setTimeInMillis(ms); cal.setTimeInMillis(ms);
return nanosFromCalendar(cal); return nanosFromCalendar(cal);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论