Skip to content

Commit

Permalink
fix: avoid ClassLoader leaks caused by SharedTimer
Browse files Browse the repository at this point in the history
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 f52bf7f
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 4 deletions.
2 changes: 1 addition & 1 deletion pgjdbc/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down
17 changes: 16 additions & 1 deletion pgjdbc/src/main/java/org/postgresql/util/SharedTimer.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}
}
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
2 changes: 1 addition & 1 deletion ubenchmark/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down

0 comments on commit f52bf7f

Please sign in to comment.