janino-compiler / janino

Janino is a super-small, super-fast Java™ compiler.
http://janino-compiler.github.io/janino
Other
1.21k stars 205 forks source link

about memory release #207

Closed codingmiao closed 11 months ago

codingmiao commented 11 months ago

I have written the following demo, which increases memory usage continuously during runtime until it encounters a memory overflow. Could you please confirm if this demo has a memory leak issue and suggest how to fix it?

import org.codehaus.commons.compiler.CompilerFactoryFactory;
import org.codehaus.commons.compiler.IClassBodyEvaluator;

import java.io.StringReader;

public class T2 {
    @FunctionalInterface
    public interface F {
        long test();
    }
    public static class CustomClassLoader extends ClassLoader {
    }

    public static void main(String[] args) throws Exception {
        for (long l = 0; l < 100000000L; l++) {
            String code = "public long test(){return " + l + ";}";
            IClassBodyEvaluator cbe = CompilerFactoryFactory.getDefaultCompilerFactory(new CustomClassLoader()).newClassBodyEvaluator();
            cbe.setImplementedInterfaces(new Class[]{F.class});
            F f = (F) cbe.createInstance(new StringReader(code));
            System.out.println(f.test());
        }
    }

}

Among them, this section of code, String code = "public long test(){return " + l + ";}";, is just a demonstration. In reality, it is dynamically passed by the user in a web service. Therefore, caching is not very meaningful. Even if I implement caching, it seems that some classes and objects generated by ClassBodyEvaluator will not be garbage collected. Over time, this will eventually result in a memory overflow.

aunkrig commented 11 months ago

Hey there,

AFAIK Janino has no memory leaks that would cause an OutOfMemoryError, however, some JVMs are notoriously bad when it comes to garbage-collecting classes and class loaders, which probably is what you observe here.

I ran your code example with an adopt_openjdk-11.0.11-9-hotspot on Windows 10, 21H2, and the memory usage stabilizes at 750...800 MB with the JVM default settings, and Janino happily cooks ClassBodyEvaluators at approx. 5000/sec.

What OS and JVM are you using? Could you please try some combinations of OS and/or JVM?

CU Arno

codingmiao commented 11 months ago

I tried switching from JDK 17 to JDK 11 and adjusted the -XX:MaxMetaspaceSize parameter. It seems that the memory usage has improved. I will continue to observe for a while. Thank you.