asciidoctor / asciidoctor-maven-plugin

A Maven plugin that uses Asciidoctor via JRuby to process AsciiDoc source files within the project.
http://asciidoctor.org
Apache License 2.0
311 stars 124 forks source link

Concurrent Modification to currentLoader: Cannot invoke "java.lang.ClassLoader.getParent()" because "this.currentLoader" is null #821

Open mxknammour opened 2 months ago

mxknammour commented 2 months ago

Thank you for taking your time to talk with us!

What is this issue about?

Description

While executing the process-asciidoc goal on a project of mine, I encountered this error:

Caused by: java.lang.NullPointerException: Cannot invoke "java.lang.ClassLoader.getParent()" because "this.currentLoader" is null
    at java.util.ServiceLoader$ModuleServicesLookupIterator.hasNext (ServiceLoader.java:1075)
    at java.util.ServiceLoader$2.hasNext (ServiceLoader.java:1309)
    at java.util.ServiceLoader$3.hasNext (ServiceLoader.java:1393)
    at org.asciidoctor.jruby.log.internal.LogHandlerRegistryExecutor.registerAllLogHandlers (LogHandlerRegistryExecutor.java:19)
    at org.asciidoctor.jruby.internal.JRubyAsciidoctor.registerLogHandlers (JRubyAsciidoctor.java:112)
    at org.asciidoctor.jruby.internal.JRubyAsciidoctor.processRegistrations (JRubyAsciidoctor.java:92)
    at org.asciidoctor.jruby.internal.JRubyAsciidoctor.create (JRubyAsciidoctor.java:69)
    at org.asciidoctor.jruby.internal.JRubyAsciidoctor.create (JRubyAsciidoctor.java:65)
    at org.asciidoctor.jruby.AsciidoctorJRuby$Factory.create (AsciidoctorJRuby.java:29)
    at org.asciidoctor.maven.AsciidoctorMojo.getAsciidoctorInstance (AsciidoctorMojo.java:398)
    at org.asciidoctor.maven.AsciidoctorMojo.processSources (AsciidoctorMojo.java:214)
    at org.asciidoctor.maven.AsciidoctorMojo.processAllSources (AsciidoctorMojo.java:166)
    at org.asciidoctor.maven.AsciidoctorMojo.execute (AsciidoctorMojo.java:156)

After taking a look at the code that caused the error:

@Override
        public boolean hasNext() {
            while (nextProvider == null && nextError == null) {
                // get next provider to load
                while (!iterator.hasNext()) {
                    if (currentLoader == null) {
                        return false;
                    } else {
                        currentLoader = currentLoader.getParent();
                        iterator = iteratorFor(currentLoader);
                    }
                }

                // attempt to load provider
                ServiceProvider provider = iterator.next();
                try {
                    @SuppressWarnings("unchecked")
                    Provider<T> next = (Provider<T>) loadProvider(provider);
                    nextProvider = next;
                } catch (ServiceConfigurationError e) {
                    nextError = e;
                }
            }
            return true;
        }

it seems that there is an if statement that handles the case in which the currentLoader is null. And yet, currentLoader.getParent() failed with a null pointer exception. This makes me believe that the issue is related to multithreading.

Is it possible that this issue was handled in recent releases so we might need to upgrade to the latest release?

Environment information

abelsromero commented 2 months ago

Is it possible that this issue was handled in recent releases so we might need to upgrade to the latest release?

Yes, if you can, I'd suggest to always use the latest 2.2.6 or 3.0.0. As well as the latest AsciidoctorJ v2.5.12, in fact the issue comes from AsciidoctorJ code, so try to upgrade it first. If you decide to try maven-plugin v3, check the docs on how to migrate from v2.x.x https://docs.asciidoctor.org/maven-tools/latest/plugin/v3-migration-guide/.