JDK-8199303 : Nashorn provides a memory leaks when using Tomcat and spark-java
  • Type: Bug
  • Component: hotspot
  • Sub-Component: jvmti
  • Affected Version: 8u144
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: os_x
  • CPU: x86_64
  • Submitted: 2018-03-06
  • Updated: 2018-03-08
  • Resolved: 2018-03-08
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Linux 2.6.32-042stab117.16
OS X 10.13.3

A DESCRIPTION OF THE PROBLEM :
When I configure spark-java application from JavaScript and run this code from Tomcat, it provides the memory leak (WebappClassloader was leaked). 

The situation is very strange. 
When I add only API GET endpoint, then no leaks. WebappClassloader correctly unload. 
When I add before or after spark filter, then WebappClassloader leaked.

I have prepared the simple code for demonstration https://bitbucket.org/lavelas/nashorn-memory-leak. 

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Pull source from https://bitbucket.org/lavelas/nashorn-memory-leak
2. Create war file by command mvn package
3. Start Tomcat
4. Deploy war from step 2 
5. Undeploy war from step 2 
6. Repeat steps 5-4 few times
7. Check memory leak report (for example in default Tomcat manager)

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No memory leaks
ACTUAL -
The WebappClassloader was leaked

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import spark.servlet.SparkApplication;

import javax.script.*;

/**
 * Spark filter with demonstration memory leak in Nashorn
 */
public class NashornSpark implements SparkApplication {

    public void init() {
        ScriptEngineManager sem = new ScriptEngineManager();
        ScriptEngine nashorn = sem.getEngineByName("nashorn");

        try {
            nashorn.eval(
                    "var spark = {};\n" +
                    "spark.before = Packages.spark.Spark.before;\n" +
                    "spark.get = Packages.spark.Spark.get;\n" +
                    "spark.before('/*', function (request, response) { print('before') });\n" + // <------ Comment this line FIX memory leak!!!
                    "spark.get('/*', function (request, response) { return 'Hello spark!' });" +
                    ""
            );
        } catch (ScriptException e) {
            e.printStackTrace();
        }
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Restart Tomcat


Comments
This issue looks duplicate of JDK-8081323 (JDK-8197544), which is already fixed in JDK10 b31. Kindly verify the issue on 10 ea builds available at - http://jdk.java.net/10/
08-03-2018