ninjaframework / ninja

Ninja is a full stack web framework for Java. Rock solid, fast and super productive.
http://www.ninjaframework.org
Apache License 2.0
1.91k stars 519 forks source link

java.lang.OutOfMemoryError: PermGen space on change + hot reload #283

Open danielsawan opened 9 years ago

danielsawan commented 9 years ago

I am using eclipse with maven to debug my project. I create a new project and integrate it to eclipse. Then i open my application.conf in order to modify application.secret property. I click on save then a hot reload happen with an error :

015-01-14 11:10:55.807:WARN:oejw.WebAppContext:Scanner-0: Failed startup of context o.e.j.m.p.JettyWebAppContext@704fdb3c ninja.lifecycle.FailedStartException: java.lang.OutOfMemoryError: PermGen space at ninja.lifecycle.LifecycleRegister.invokeTarget(LifecycleRegister.java:103) at ninja.lifecycle.LifecycleRegister.start(LifecycleRegister.java:55) at ninja.lifecycle.LifecycleServiceImpl.start(LifecycleServiceImpl.java:84) at ninja.NinjaDefault.onFrameworkStart(NinjaDefault.java:125) at ninja.servlet.NinjaBootstrap.boot(NinjaBootstrap.java:90)

I tried then to modify the memory of my pom file by adding

<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <fork>true</fork>
                    <meminitial>1024m</meminitial>
                    <maxmem>2024m</maxmem>
                </configuration>
            </plugin>

But this didn't solve the problem.

Any idea about how to solve this issue using eclipse / maven plugin ?

danielsawan commented 9 years ago

I finally found the solution by adding

-Xms1024m -Xmx10240m -XX:PermSize=256m -XX:MaxPermSize=1024m

to the debug profile like shown here

http://puu.sh/ev9lB/da41b4835f.png

raphaelbauer commented 9 years ago

thanks for posting the solution!

danielsawan commented 9 years ago

It seems like it report the problem to later. I had this bug again. As if each time a new hot code reload is made, all the class are added to the PermSize again and again without cleaning older entity until the java.lang.OutOfMemoryError: PermGen space

raphaelbauer commented 9 years ago

We got the SuperDevMode to exactly solve that problem. There are libraries used by Ninja that don't clean up after themselves and causing the PermGem exceptions (aka Classloader leaks).

I am not sure we can do anything about it. You can of course try to find and fix the root cause :)

In production those kind of errors are not a problem btw.

danielsawan commented 9 years ago

Oh in eclipse i was using mvn jetty:run instead of ninja:run don't ask me why...

danielsawan commented 9 years ago

lol i am so noob everything is explained here http://www.ninjaframework.org/documentation/basic_concepts/super_dev_mode.html

Why If you develop your applications you want super fast round trips. Deploying you application to an application server and waiting a long time until stuff is ready is just not productive.

On the other hand there is already seemingly good solution: the jetty-maven-plugin and the jetty:run goal.

Unfortunately jetty-maven-plugin and its jetty:run goal often leads to PermGen exceptions that block your JVM and cause nasty interruptions to productivity.

Therefore we developed Ninja’s SuperDevMode. SuperDevMode does not suffer any PermGen exceptions and picks up any changes in your code really fast.

By the way i understood why i had jetty:run because it is written in the doc : http://www.ninjaframework.org/documentation/debugging.html http://www.ninjaframework.org/documentation/deployment.html

Maybe we should replace all jetty:run by ninja:run ?

danielsawan commented 9 years ago

i just understand that if we want hot reload working without PermGen exception we have to use ninja:run. If we want to debug we have to use jetty:run and setting the properties : jpda.listen=maven.

I tried to debug using ninja:run but this don't work because it is not pluged to the jetty directly but to the "jetty reloader"

So am i right to say that we can't debug without having permgen exception ?

I also found this if it can help : http://www.eclipse.org/jetty/documentation/current/preventing-memory-leaks.html

raphaelbauer commented 9 years ago

debugging is no problem. But debugging + hot code swapping may not work for a very long debugging session.

danielsawan commented 9 years ago

Yes that's the problem. I am used when i create a project from scratch to hot reload on change and put some breakpoint when i want to debug and remove then when i finish but continuing on the same environnement setup.

With ninja i feel like it is a little bit "buggy" because we have to develop using ninja:run then to debug we have to kill the process and run jetty:run. Once we finish debugging we have to kill jetty:run to start again ninja:run. And i am not talking about the fact that when you stop a ninja:run process you still have to open your process explorer and kill the jetty instance that still here in order to stop all the ninja:run child process.

I am definitly not as pro as the ninja team but are you guys happy with that ? There is nothing wrong here to you ?

Is it possible to make the ninja:run automaticly reconnect to the debug port of the jetty instance at each restart ? like that we could debug using ninja:run instead of jetty:run ?

momiji commented 9 years ago

I found a way to do it... #365 for my comments, and I'll create a new PR soon...

mvn ninja:run \
   -Dninja.jvmArgs="-Dninja.external.configuration=dev.conf -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000" \
   -Dninja.watchDirs=.
facundofarias commented 8 years ago

You rock! :+1: