You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by bu...@apache.org on 2019/07/26 10:14:07 UTC

[Bug 63612] New: PooledConnection#connectUsingDriver, Thread.currentThread().getContextClassLoader() is null

https://bz.apache.org/bugzilla/show_bug.cgi?id=63612

            Bug ID: 63612
           Summary: PooledConnection#connectUsingDriver,
                    Thread.currentThread().getContextClassLoader() is null
           Product: Tomcat Modules
           Version: unspecified
          Hardware: All
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: jdbc-pool
          Assignee: dev@tomcat.apache.org
          Reporter: clemensdev@mysign.ch
  Target Milestone: ---

From time to time we are facing the follwing exception (call stack):
...
Caused by: java.sql.SQLException: Unable to load class: org.mariadb.jdbc.Driver
from ClassLoader:http://java.net.URLClassLoader@4c873330;ClassLoader:null
        at
org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:292)
        at
org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:212)
        at
org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:736)
        at
org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:668)
        at
org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:198)
        at
org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:132)
        at org.apache.torque.Torque.getConnection(Torque.java:924)
        ... 53 common frames omitted
Caused by: java.lang.ClassNotFoundException: Unable to load class:
org.mariadb.jdbc.Driver from
ClassLoader:http://java.net.URLClassLoader@4c873330;ClassLoader:null
        at
org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56)
        at
org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:280)
        ... 59 common frames omitted
Caused by: java.lang.ClassNotFoundException: Classloader is null
        at
org.apache.tomcat.jdbc.pool.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:40)
        ... 60 common frames omitted

According to the code (in PooledConnection# connectUsingDriver)
Thread.currentThread().getContextClassLoader() returns null

Googling for " Thread.currentThread().getContextClassLoader() is null" the
common demoniator seems to be `getContextClassLoader can be null`. If this is
true there should be
a) a null-check in PooledConnection#connectUsingDriver
b) if null, then there should be a fallback-Classloader (the system class
laoder?)

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 63612] PooledConnection#connectUsingDriver, Thread.currentThread().getContextClassLoader() may be null

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=63612

--- Comment #8 from clemensdev@mysign.ch ---
looking into the logs of the "affected site" I guess to have made up a "common
denominator" for the "the null TCCL in that thread".

All callstacks "originate" from a parallelStream execution
(java.util.Collection.parallelStream())!

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 63612] PooledConnection#connectUsingDriver, Thread.currentThread().getContextClassLoader() is null

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=63612

--- Comment #1 from clemensdev@mysign.ch ---
Context:
Debian GNU/Linux 9 \n \l
java version 1.8.0_162
Tomcat 8.5.35

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 63612] PooledConnection#connectUsingDriver, Thread.currentThread().getContextClassLoader() may be null

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=63612

clemensdev@mysign.ch changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|PooledConnection#connectUsi |PooledConnection#connectUsi
                   |ngDriver,                   |ngDriver,
                   |Thread.currentThread().getC |Thread.currentThread().getC
                   |ontextClassLoader() is null |ontextClassLoader() may be
                   |                            |null

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 63612] PooledConnection#connectUsingDriver, Thread.currentThread().getContextClassLoader() may be null

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=63612

--- Comment #2 from clemensdev@mysign.ch ---
Unfortunately not easily extractable/reproducible

Maybe :

th = new Thread() {
@Override
public void run() {
« do something that requires a connection from the pool »
}
} ;
th.set getContextClassLoader( null ) ; 
th.run() ;

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 63612] PooledConnection#connectUsingDriver, Thread.currentThread().getContextClassLoader() may be null

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=63612

--- Comment #5 from clemensdev@mysign.ch ---
>Um... why would you do such a thing?
for the unit test only to force Thread.currentThread().getContextClassLoader()
to be null ;-)

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 63612] PooledConnection#connectUsingDriver, Thread.currentThread().getContextClassLoader() may be null

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=63612

--- Comment #9 from Mark Thomas <ma...@apache.org> ---
That is likely because of the fix to this memory leak:
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8172726

The Fork/Join framework in the JRE does not play nicely with the per web
application classloader environment. In Java 7/8 you get memory leaks and
security issues (Tomcat protects against these by default) and in Java 9 you
get a null TCCL.

There really isn't a simple solution to this issue for code that depends on
ForkJoinPool.commonPool().

I'll note that JNDI (which depends on the TCCL to identify the correct
InitialContext) is also going to fail for similar reasons.

If you only have a single web application then you can work-around it by using
a custom thread factory for the common fork/join pool that essentially restores
the Java 7/8 behaviour but even then you won't be able to reload the web
application (as that triggers a change in class loader).

You may also be able to work-around it be explicitly passing the correct class
loader to the task and setting the TCCL for the duration of the task.

I'm leaning towards closing this as INVALID as it is not an issue with
jdbc-pool.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 63612] PooledConnection#connectUsingDriver, Thread.currentThread().getContextClassLoader() may be null

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=63612

Christopher Schultz <ch...@christopherschultz.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |NEEDINFO

--- Comment #3 from Christopher Schultz <ch...@christopherschultz.net> ---
(In reply to clemensdev from comment #2)
> th.set getContextClassLoader( null ) ; 
> th.run() ;

Um... why would you do such a thing?

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 63612] PooledConnection#connectUsingDriver, Thread.currentThread().getContextClassLoader() is null

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=63612

clemensdev@mysign.ch changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Severity|normal                      |critical

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 63612] PooledConnection#connectUsingDriver, Thread.currentThread().getContextClassLoader() may be null

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=63612

--- Comment #7 from clemensdev@mysign.ch ---
Thx Konstatin
>I think that you can avoid this error if you put the 
>database driver into the same classloader where 
>tomcat-jdbc.jar was loaded from
mariadb-connector.jar is indeed not in the same directory as tomcat-jdbc.jar,
i.e. not in the "lib" directory of Tomcat.
The site we are seeing theses exceptions only in "certain circumstances"
(whtever these are, high load?) throws the exceptions ...

>You would better find the rood cause behind the null TCCL in that thread
I completely agree

>If "Thread.currentThread().getContextClassLoader()" is 
>null, it essentially means that this thread is not associated 
>with a web application
how can a thread 
a) not be associated with the web application?
b) have no class loader?

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 63612] PooledConnection#connectUsingDriver, Thread.currentThread().getContextClassLoader() may be null

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=63612

--- Comment #6 from Konstantin Kolinko <kn...@gmail.com> ---
1. If "Thread.currentThread().getContextClassLoader()" is null, it essentially
means that this thread is not associated with a web application.

(Thus it cannot access the classes provided by web application, cannot use log
configuration specific to this web application and so on).


2. ClassLoaderUtil.loadClass(ClassLoaderUtil.java:56) does a loop over an array
of ClassLoaders.

The following line

   throw new ClassNotFoundException("Classloader is null");

just simulates a ClassNotFoundException that is is thrown in the non-null
branch (by the "Class.forName(..)" call) when the class is not found.

3. The TCCL is the last ClassLoader in the array, so there are no more
classloaders to try.


The handling of the null value may be improved, but I see nothing more than
providing a different error message. The result will be the same
ClassNotFoundException.

I guess that this is not what you are looking for.


1. I think that you can avoid this error if you put the database driver into
the same classloader where tomcat-jdbc.jar was loaded from. That is: into the
"lib" directory of Tomcat, like people did in the good old times.

(I guess that you bundled the database driver with you web application.)

2. You would better find the rood cause behind the null TCCL in that thread.

Even if you avoid the driver loading issue, the thread may experience other
oddities. What comes to mind:
- a wrong logging configuration,
- being unable to access JNDI directory.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 63612] PooledConnection#connectUsingDriver, Thread.currentThread().getContextClassLoader() may be null

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=63612

--- Comment #4 from romain.manni-bucau <rm...@gmail.com> ---
Some libs do but pool and pool tries first tomcatjdbc classloader so if the
driver is in the webapp it fails. Init should cache the value per webapp imho.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org