DriverManagerCleanUp can't really work for many scenarios #80
DriverManagerCleanUp can't really work for many scenarios #80Geker wants to merge 18 commits intomjiderhamn:masterfrom
Conversation
Add getAllDrivers method. DriverManager.getDrivers() only return the drivers which be load by caller(DriverManagerCleanUp.class). For many scenarios the Caller is not the same classloader which load the jdbc Drivers
|
Could you please adhere to the coding standards of the project, such as indentation with 2 spaces, camel humping etc? |
| /** | ||
| * Deregister JDBC drivers loaded by classloader | ||
| * | ||
| * |
There was a problem hiding this comment.
Why these empty JavaDoc lines?
There was a problem hiding this comment.
sorry I use the diffenrent Java code style template ,i shoud follow your project coding standards
| catch (Exception e) { | ||
| preventor.warn("get All registeredDrivers Exception "); | ||
| preventor.error(e); | ||
|
|
There was a problem hiding this comment.
Can't we default to DriverManager.getDrivers() in case reflection fails?
| } | ||
| catch (Exception e) { | ||
| preventor.warn("get All registeredDrivers Exception "); | ||
| preventor.error(e); |
There was a problem hiding this comment.
We should decide whether this makes up a warning or an error - not both
| preventor.error(e); | ||
|
|
||
| } | ||
| return (result.elements()); |
| public class DriverManagerCleanUp implements ClassLoaderPreMortemCleanUp { | ||
| @Override | ||
| public void cleanUp(ClassLoaderLeakPreventor preventor) { | ||
| final List<Driver> driversToDeregister = new ArrayList<Driver>(); |
There was a problem hiding this comment.
Is this list even needed now that we know we won't cause ConcurrentModificationException (depending on the reflectino fall below, by all means), or can't we deregister in the first loop?
There was a problem hiding this comment.
yes,driversToDeregister is no need any more.
| final Enumeration<Driver> allDrivers = getAllDrivers(preventor); | ||
| while (allDrivers.hasMoreElements()) { | ||
| final Driver driver = allDrivers.nextElement(); | ||
| if (preventor.isLoadedInClassLoader(driver)) // Should be true for all returned by DriverManager.getDrivers() |
There was a problem hiding this comment.
Is the comment still relevant?
| * | ||
| * @param preventor | ||
| * @return | ||
| */ |
| * @param preventor | ||
| * @return | ||
| */ | ||
| public java.util.Enumeration<Driver> getAllDrivers(ClassLoaderLeakPreventor preventor) { |
There was a problem hiding this comment.
Why Enumeration rather than Collection?
There was a problem hiding this comment.
DriverManager.getDrivers() return type is Enumeration
| * @return | ||
| */ | ||
| public java.util.Enumeration<Driver> getAllDrivers(ClassLoaderLeakPreventor preventor) { | ||
| java.util.Vector<Driver> result = new java.util.Vector<Driver>(); |
There was a problem hiding this comment.
Why Vector rather than ArrayList? Synchronization cannot possibly be needed.
There was a problem hiding this comment.
because method DriverManager.getDrivers() use Vector,So i follow the usage
| public java.util.Enumeration<Driver> getAllDrivers(ClassLoaderLeakPreventor preventor) { | ||
| java.util.Vector<Driver> result = new java.util.Vector<Driver>(); | ||
| try { | ||
| CopyOnWriteArrayList<?> driverinfos = preventor.getStaticFieldValue(DriverManager.class, "registeredDrivers"); |
There was a problem hiding this comment.
I suggest using List (or even Collection) as the variable type, and by all means keep CopyOnWriteArrayList as a comment. That way this class still works even if the internals of DriverManager is updated to use something other than CopyOnWriteArrayList
|
What is the scenario we're trying to solve here? The leak prevention library being part of a framework/application server, while the JDBC driver is dynamically loaded in an application instance (.war file)? |
|
Yes I have a app server. which have two level classloader. the server classloader load classloader-leak-prevention.jar .The server main-thread execute: runPreClassLoaderInitiators -> start war classloader (war-classloader load jdbc drivers / .war etc)->runCleanUps I modify the code, please see the code again. |
modify code style; return DriverManager.getDrivers() if Exception occurred
| * @param preventor | ||
| * @return All drivers in DriverManager's registeredDrivers field,or | ||
| * DriverManager.getDrivers() if exception occurred | ||
| */ |
There was a problem hiding this comment.
Please clean up the JavaDoc a bit. (For example, you don't need to document method X with "Add X method". Either add documentation or remove @param)
| } | ||
| } catch (Exception e) { | ||
| preventor.warn("get All registeredDrivers Exception"); | ||
| return DriverManager.getDrivers(); |
There was a problem hiding this comment.
The code now assumes the returned Enumeration does not cause ConcurrentModificationException if driver is removed while looping. Is that guaranteed by the API contract, or should we make of copy to ensure the library does not start failing in case the DriverManager internals happens to be changed?
There was a problem hiding this comment.
I think it's no reason the jdk developer to changed the default manner of getDrivers. they are already considered avoid ConcurrentModificationException in current code.
| preventor.warn("get All registeredDrivers Exception"); | ||
| return DriverManager.getDrivers(); | ||
| } | ||
| return result.elements(); |
There was a problem hiding this comment.
Move this inside try (unless used for copying, see below)
| * DriverManager.getDrivers() if exception occurred | ||
| */ | ||
| public Enumeration<Driver> getAllDrivers(ClassLoaderLeakPreventor preventor) { | ||
| Vector<Driver> result = new java.util.Vector<Driver>(); |
There was a problem hiding this comment.
Move this inside try (unless used for copying, see below)
|
|
|
Good catch @OlegYch ! |
|
@OlegYch thanks your advices. |
Summary: In java 9, sun.misc.GC is moved to sun.rmi.transport.GC , trying again if sun.misc.GC is not found else throwing ClassNotFoundException.
Conflicts: README.md classloader-leak-prevention/classloader-leak-prevention-core/README.md
Conflicts: classloader-leak-prevention/classloader-leak-prevention-core/pom.xml classloader-leak-prevention/classloader-leak-prevention-servlet/pom.xml classloader-leak-prevention/classloader-leak-prevention-servlet3/pom.xml classloader-leak-prevention/pom.xml
This reverts commit 6a13eff.
Conflicts: classloader-leak-prevention/classloader-leak-prevention-core/pom.xml classloader-leak-prevention/classloader-leak-prevention-servlet/pom.xml classloader-leak-prevention/classloader-leak-prevention-servlet3/pom.xml classloader-leak-prevention/pom.xml
...ore/src/main/java/se/jiderhamn/classloader/leak/prevention/cleanup/DriverManagerCleanUp.java
Outdated
Show resolved
Hide resolved
...ore/src/main/java/se/jiderhamn/classloader/leak/prevention/cleanup/DriverManagerCleanUp.java
Outdated
Show resolved
Hide resolved
...ore/src/main/java/se/jiderhamn/classloader/leak/prevention/cleanup/DriverManagerCleanUp.java
Outdated
Show resolved
Hide resolved
...ore/src/main/java/se/jiderhamn/classloader/leak/prevention/cleanup/DriverManagerCleanUp.java
Outdated
Show resolved
Hide resolved
...ore/src/main/java/se/jiderhamn/classloader/leak/prevention/cleanup/DriverManagerCleanUp.java
Outdated
Show resolved
Hide resolved
...ore/src/main/java/se/jiderhamn/classloader/leak/prevention/cleanup/DriverManagerCleanUp.java
Outdated
Show resolved
Hide resolved
...ore/src/main/java/se/jiderhamn/classloader/leak/prevention/cleanup/DriverManagerCleanUp.java
Outdated
Show resolved
Hide resolved
...ore/src/main/java/se/jiderhamn/classloader/leak/prevention/cleanup/DriverManagerCleanUp.java
Outdated
Show resolved
Hide resolved
...ore/src/main/java/se/jiderhamn/classloader/leak/prevention/cleanup/DriverManagerCleanUp.java
Outdated
Show resolved
Hide resolved
...ore/src/main/java/se/jiderhamn/classloader/leak/prevention/cleanup/DriverManagerCleanUp.java
Outdated
Show resolved
Hide resolved
|
I accept your suggestion,please review again. |
DriverManager.getDrivers() only return the drivers which be load by caller(DriverManagerCleanUp.class).
For many scenarios the Caller is not the same classloader which load the jdbc Drivers. So ,DriverManager.getDrivers() will return empty driver list,and DriverManagerCleanUp do nothing.
I think it need get registeredDrivers by reflection.