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 2020/06/08 09:09:29 UTC

[Bug 64503] New: ClassNotFoundException: org.apache.naming.java.javaURLContextFactory using java.util.Collection.parallelStream()

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

            Bug ID: 64503
           Summary: ClassNotFoundException:
                    org.apache.naming.java.javaURLContextFactory using
                    java.util.Collection.parallelStream()
           Product: Tomcat 9
           Version: 9.0.35
          Hardware: PC
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Servlet
          Assignee: dev@tomcat.apache.org
          Reporter: mseele@guh-software.de
  Target Milestone: -----

Created attachment 37293
  --> https://bz.apache.org/bugzilla/attachment.cgi?id=37293&action=edit
context.xml (to reproduce the problem)

Steps to reproduce:

- Use the attached context.xml
- Add the attached SimpleContextListener class into a war
- Start tomcat with the war

The following exception occurs:

java.lang.RuntimeException: java.lang.RuntimeException: Error on lookup
        at
java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native
Method)
        at
java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at
java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at
java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
        at
java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:600)
        at
java.base/java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:678)
        at
java.base/java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:737)
        at
java.base/java.util.stream.ReduceOps$ReduceOp.evaluateParallel(ReduceOps.java:919)
        at
java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
        at
java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
        at
SimpleContextListener.contextInitialized(SimpleContextListener.java:26)
        at
org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4686)
        at
org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5147)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at
org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384)
        at
org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at
org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
        at
java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140)
        at
org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
        at
org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:841)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at
org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384)
        at
org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at
org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
        at
java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140)
        at
org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
        at
org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at
org.apache.catalina.core.StandardService.startInternal(StandardService.java:421)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at
org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.startup.Catalina.start(Catalina.java:633)
        at
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:343)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:474)
Caused by: java.lang.RuntimeException: Error on lookup
        at SimpleContextListener.lambda$0(SimpleContextListener.java:24)
        at
java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
        at
java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
        at
java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
        at
java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
        at
java.base/java.util.stream.ReduceOps$ReduceTask.doLeaf(ReduceOps.java:952)
        at
java.base/java.util.stream.ReduceOps$ReduceTask.doLeaf(ReduceOps.java:926)
        at
java.base/java.util.stream.AbstractTask.compute(AbstractTask.java:327)
        at
java.base/java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:746)
        at
java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
        at
java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
        at
java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
        at
java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
        at
java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177)
Caused by: javax.naming.NoInitialContextException: Cannot instantiate class:
org.apache.naming.java.javaURLContextFactory [Root exception is
java.lang.ClassNotFoundException: org.apache.naming.java.javaURLContextFactory]
        at
java.naming/javax.naming.spi.NamingManager.getFactory(NamingManager.java:749)
        at
java.naming/javax.naming.spi.NamingManager.lambda$getInitialContext$1(NamingManager.java:711)
        at
java.base/jdk.internal.loader.AbstractClassLoaderValue$Memoizer.get(AbstractClassLoaderValue.java:329)
        at
java.base/jdk.internal.loader.AbstractClassLoaderValue.computeIfAbsent(AbstractClassLoaderValue.java:205)
        at
java.naming/javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:711)
        at
java.naming/javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:305)
        at
java.naming/javax.naming.InitialContext.init(InitialContext.java:236)
        at
java.naming/javax.naming.InitialContext.<init>(InitialContext.java:184)
        at
java.naming/javax.naming.InitialContext.doLookup(InitialContext.java:282)
        at SimpleContextListener.lambda$0(SimpleContextListener.java:22)
        ... 13 more
Caused by: java.lang.ClassNotFoundException:
org.apache.naming.java.javaURLContextFactory
        at
java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
        at
java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
        at java.base/java.lang.Class.forName0(Native Method)
        at java.base/java.lang.Class.forName(Class.java:398)
        at
java.naming/com.sun.naming.internal.VersionHelper.loadClass(VersionHelper.java:123)
        at
java.naming/com.sun.naming.internal.VersionHelper.loadClass(VersionHelper.java:96)
        at
java.naming/javax.naming.spi.NamingManager.getFactory(NamingManager.java:746)
        ... 22 more

This happens because of parallelStream(). Using stream() everything works.

I tried several "workarounds" like https://stackoverflow.com/a/49113343/2523032
butz all of them failed.

-- 
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 64503] ClassNotFoundException: org.apache.naming.java.javaURLContextFactory using java.util.Collection.parallelStream()

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

Michael Seele <ms...@guh-software.de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 OS|                            |All

--- Comment #2 from Michael Seele <ms...@guh-software.de> ---
This happens with Java 11.0.7+10 (AdoptOpenJDK)

-- 
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 64503] ClassNotFoundException: org.apache.naming.java.javaURLContextFactory using java.util.Collection.parallelStream()

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

--- Comment #1 from Michael Seele <ms...@guh-software.de> ---
Created attachment 37294
  --> https://bz.apache.org/bugzilla/attachment.cgi?id=37294&action=edit
java object (to reproduce the problem)

-- 
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 64503] ClassNotFoundException: org.apache.naming.java.javaURLContextFactory using java.util.Collection.parallelStream()

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

Mark Thomas <ma...@apache.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |WONTFIX
             Status|NEW                         |RESOLVED

--- Comment #3 from Mark Thomas <ma...@apache.org> ---
Sorry, this is by design.

JNDI relies on the ThreadContextClassLoader (TCCL) being set to correctly
identify the correct JNDI Context for the web application. Tomcat ensures that
threads used to serve requests have the correct TCCL set at the start and also
ensure the TCCL is cleared at the end to avoid memory leaks and potential
security issues.

parallelStream() uses ForkJoinPool/ForkJoinTask which has its own internal
thread pool that has no knowledge of these TCCL requirements.

I'm guessing what you have presented is a simplified test case and the real
problem is rather more complex. You should be able to pass in the correct TCCL
and have the code use it. I am assuming that the additional complexity of
passing and using the TCCL is worth it for the benefit of performing the tasks
in parallel. However be aware that:
- you need to use a try/finally block to ensure the TCCL is reset after use
- depending on your Tomcat settings (defaults should not do this) it may be the
case that ForkJoinPool is using a thread pool that produces threads where you
can't set the TCCL.

Some background you might find interesting:
http://tomcat.markmail.org/thread/7w5wspqeayx7dr5x
http://tomcat.markmail.org/thread/qcy6rqhw52sspyv7

-- 
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 64503] ClassNotFoundException: org.apache.naming.java.javaURLContextFactory using java.util.Collection.parallelStream()

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

--- Comment #4 from Michael Seele <ms...@guh-software.de> ---
Thanks for the answer, Mark.

Just for the record, here is how I solved it:

I created a new helper method that acts like a wrapper for the mapping
function:

public static <T, R> Function<T, R> parallel(Function<T, R> function) {
        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
        return input -> {
                Thread thread = Thread.currentThread();
                ClassLoader originalTccl = thread.getContextClassLoader();
                try {
                        thread.setContextClassLoader(tccl);
                        return function.apply(input);
                } finally {
                        thread.setContextClassLoader(originalTccl);
                }
        };
}

The method is used this way and solves the problem:

List<String> values = keys.parallelStream().map(parallel(key -> {
        try {
                return (String) InitialContext.doLookup(DEFAULT_CONTEXT + key);
        } catch (NamingException e) {
                throw new RuntimeException("Error on lookup", e); //$NON-NLS-1$
        }
})).collect(Collectors.toList());

-- 
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