Skip to content
Permalink
Browse files

fix: avoid ClassLoader leaks caused by SharedTimer

Avoid ClassLoader leaks caused by the TimerThread started by SharedTimer inheriting the contextClassLoader of the currently executing thread and the AccessControlContext containing ProtectionDomains with calling code.

closes #664
  • Loading branch information
vlsi committed Oct 29, 2016
1 parent 8be516d commit f52bf7fc7a71341fae3a9255af0e2b2c271a35dd
@@ -3,7 +3,7 @@
<parent>
<groupId>org.postgresql</groupId>
<artifactId>pgjdbc-core-parent</artifactId>
<version>1.1.1</version>
<version>1.1.2</version>
<relativePath />
</parent>

@@ -30,7 +30,22 @@ public int getRefCount() {
public synchronized Timer getTimer() {
if (timer == null) {
int index = timerCount.incrementAndGet();
timer = new Timer("PostgreSQL-JDBC-SharedTimer-" + index, true);

/*
Temporarily switch contextClassLoader to the one that loaded this driver to avoid TimerThread preventing current
contextClassLoader - which may be the ClassLoader of a web application - from being GC:ed.
*/
final ClassLoader prevContextCL = Thread.currentThread().getContextClassLoader();
try {
/*
Scheduled tasks whould not need to use .getContextClassLoader, so we just reset it to null
*/
Thread.currentThread().setContextClassLoader(null);

timer = new Timer("PostgreSQL-JDBC-SharedTimer-" + index, true);
} finally {
Thread.currentThread().setContextClassLoader(prevContextCL);
}
}
refCount.incrementAndGet();
return timer;
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2016, PostgreSQL Global Development Group
* See the LICENSE file in the project root for more information.
*/

package org.postgresql.test.util;

import org.postgresql.Driver;

import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import se.jiderhamn.classloader.PackagesLoadedOutsideClassLoader;
import se.jiderhamn.classloader.leak.JUnitClassloaderRunner;
import se.jiderhamn.classloader.leak.Leaks;

/**
* Test case that verifies that the use of {@link org.postgresql.util.SharedTimer} within
* {@link org.postgresql.Driver} does not cause ClassLoader leaks
* @author Mattias Jiderhamn
*/
@RunWith(JUnitClassloaderRunner.class)
@PackagesLoadedOutsideClassLoader(packages = "org.postgresql", addToDefaults = true)
public class SharedTimerClassLoaderLeakTest {

/** Starting a {@link org.postgresql.util.SharedTimer} should not cause ClassLoader leaks */
@Leaks(false)
@Test
public void sharedTimerDoesNotCauseLeak() {
Driver.getSharedTimer().getTimer(); // Start timer
}

@After
public void tearDown() {
Driver.getSharedTimer().releaseTimer();
}
}
@@ -3,7 +3,7 @@
<parent>
<groupId>org.postgresql</groupId>
<artifactId>pgjdbc-versions</artifactId>
<version>1.1.1</version>
<version>1.1.2</version>
</parent>

<artifactId>pgjdbc-aggregate</artifactId>
@@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
<parent>
<groupId>org.postgresql</groupId>
<artifactId>pgjdbc-versions</artifactId>
<version>1.1.1</version>
<version>1.1.2</version>
<relativePath />
</parent>

0 comments on commit f52bf7f

Please sign in to comment.
You can’t perform that action at this time.