#1669 new
Israel Tsadok

Seemingly random ClassNotFoundException on first request

Reported by Israel Tsadok | May 13th, 2013 @ 06:04 AM

Framework version: Play 1.2.4, also appears in 1.2.5
Platform you're using: Ubuntu 12.04

This bug was very hard to reproduce and I'm still not sure about what triggers it exactly. What we would see was after every server restart, a bunch of ClassNotFoundException for classes that look like part of our code, but with "BeanInfo" or "Customizer" added at the end. The exceptions are always thrown from play.classloading.ApplicationClasses.getAnnotatedClass(ApplicationClasses.java:96). This behavior happened almost exclusively on the production system.

Turns out that these non-existing classes get added to the classes Map, and then cause the exception when the classloader tries to load them. To find out what was doing this, I added a stack trace right before classes.put(name, new ApplicationClass(name)) no line 48. I'm attaching the result. It seems like groovy does this while compiling the templates. Notice that the file has two unrelated traces in it.

Also note that these are not real exceptions. I just threw an Excption and caught it immediately to get the stack trace.

Before adding a class name to the classes map, there's a check that getJava(name) is not null. This should help avoid adding most non-existent classes, except inner classes. That is why you see class names like Secure$SecurityBeanInfo.

I "fixed" the issue locally by adding a condition to line 48 like so:


if (!classes.containsKey(name) && getJava(name) != null && !name.endsWith("BeanInfo") && name.endsWith("Customizer")) {

This is not a good general fix, but I'm not sure what is. Possibly making getJava actually look into the file to find the class name.

Comments and changes to this ticket

  • ricky

    ricky May 1st, 2014 @ 05:32 AM

    I have come across this exact same issue.

    The problem only happens on PROD mode.
    It seem to happen ONLY at server start.
    And it happened when ActionInvoker is parsing parameters to pass to Controller.

    The result was intermittent "No Route" or "Null Pointer" Exceptions because ActionInvoker calls Binder and it fails silently at line 202:
    } catch (Exception e) { Validation.addError(paramNode.getOriginalKey(), "validation.invalid"); }

    The exception in the code above is the same exception pointed out by OP, which is classnotfoundexception triggered by ApplicationClasses.

  • Andrei Solntsev

    Andrei Solntsev June 5th, 2015 @ 04:29 PM

    • Tag set to wtf code

    Hi!
    After a few hours of deep-night debugging, I have found cause of the problem.

    It's class ApplicationClassloader:

    public class ApplicationClassloader extends ClassLoader {
    // ~~~~~~~~~~~~~~~~~~~~~~~
    public Class<?> loadApplicationClass(String name) {    // name == 'models.Loan$RepaymentBeanInfo'
        ...
    
    1:  ApplicationClass applicationClass = Play.classes.getApplicationClass(name);
            // This getApplicationClass() actually adds a new "class" to the global list: 
            // Play.classes.put(name, new ApplicationClass(name, javaFile));
    
        // ... here goes 45 lines of code ...
    
        if (!applicationClass.compile()) {  // this compiles "Loan.java" - it takes some time
    2:      Play.classes.classes.remove(name);
            return null;
        }
        return null;
    }
    

    During the period between 1: and 2: the global list Play.classes contains "class" named Loan$RepaymentBeanInfo (that actually does not exist). If some other thread calls "Play.classloader.getAllClasses()", it will get "ClassNotFoundException: Loan$RepaymentBeanInfo" exception.

    The moral of this sad story is that global variable (that is simultaneously changed by different classes) is evil.

    I am going to create a pull request for fixing this problem.

  • R.Rettig

    R.Rettig June 10th, 2015 @ 08:25 AM

    The problem is not with compile time at all, it is just a bad sync ( the problem is the same if you use precompiled app).
    Use play.pool > 1 ( play.pool = 1 is funny for DEV but not really useful for testing ) and if you have some sophisticated web app with heavy ajax calls (which means many request) you will probably get more deep insight of this nightmare.
    Maybe the play tests will fail randomly if the 'play.pool' property would be increased by default for testing the framework.

  • R.Rettig

    R.Rettig June 16th, 2015 @ 12:57 PM

    • Assigned user set to “Alex”

    Promise p = new Job("I am going to create a pull request for fixing this problem.").now();
    https://github.com/playframework/play1/pull/886 = p.get();

    For test which have tracing enabled you will see possible wrong classes loaded before (e.g. 'just-test-cases' ):

    samples-and-tests/just-test-cases/test-result/application.log:7798:16 Jun 2015 14:09:13,709 TRACE ~ p.c.ApplicationClassloader.loadApplicationClass:: dynamic bytecode compile/enhence: java.lang.NoClassDefFoundError: models/OptimisticLockingModelPlayTest$TestModel_ (wrong name: models/OptimisticLockingModelPlayTest$TestModel)
    samples-and-tests/just-test-cases/test-result/application.log:20608:16 Jun 2015 14:09:42,921 TRACE ~ p.c.ApplicationClassloader.loadApplicationClass:: dynamic bytecode compile/enhence: java.lang.NoClassDefFoundError: TemplateClassBindingTest$StaticInnerClass$class (wrong name: TemplateClassBindingTest$StaticInnerClass)
    samples-and-tests/just-test-cases/logs/system.out:7804:14:09:13,709 TRACE ~ p.c.ApplicationClassloader.loadApplicationClass:: dynamic bytecode compile/enhence: java.lang.NoClassDefFoundError: models/OptimisticLockingModelPlayTest$TestModel_ (wrong name: models/OptimisticLockingModelPlayTest$TestModel)
    samples-and-tests/just-test-cases/logs/system.out:20637:14:09:42,921 TRACE ~ p.c.ApplicationClassloader.loadApplicationClass:: dynamic bytecode compile/enhence: java.lang.NoClassDefFoundError: TemplateClassBindingTest$StaticInnerClass$class (wrong name: TemplateClassBindingTest$StaticInnerClass)
    
  • Brandon36

    Brandon36 April 12th, 2019 @ 01:28 PM

    I learn these things by doing practice and I did my best for these things. The best essay helps me a lot when I just start doing programming in my college life.

  • malavika
  • bagio0007

    bagio0007 April 30th, 2019 @ 10:01 AM

    This is one of the best brass die casting process business-related pages which is providing useful services for readers all over the world. the collection of different areas are the main advantage of this page. The readers are able to handle a wide variety of topics easily through this site.

  • sophia345

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2>Play framework</h2>

Play makes it easier to build Web applications with Java. It is a clean alternative to bloated Enterprise Java stacks. It focuses on developer productivity and targets RESTful architectures. Learn more on the <a href="http://www.playframework.org">http://www.playframework.org</a> website.<br><br>

<h2>Source code is hosted on github</h2>Check out our repository at <a href="http://github.com/playframework/play">http://github.com/playframework/play</a><br><br>

<h2>Contributing, creating a patch</h2> Please read the <a href="http://play.lighthouseapp.com/projects/57987/contributor-guide">contributor guide</a><br><br>

<h2>Reporting Security Vulnerabilities</h2> Since all bug reports are public, please report any security vulnerability directly to <em>guillaume dot bort at gmail dot com</em>.<br><br>

<h2>Creating a bug report</h2> Bug reports are incredibly helpful, so take time to report bugs and request features in our ticket tracker. We’re always grateful for patches to Play’s code. Indeed, bug reports with attached patches will get fixed far quickly than those without any.<br><br>

Please include as much relevant information as possible including the exact framework version you're using and a code snippet that reproduces the problem.<br><br>

Don't have too much expectations. Unless the bug is really a serious "everything is broken" thing, you're creating a ticket to start a discussion. Having a patch (or a branch on Github we can pull from) is better, but then again we'll only pull high quality branches that make sense to be in the core of Play.

Attachments

Tags

Pages