Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed the Reference of the metaclass in ClassInfo.java to use a Weak… #968

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

NecOnIce
Copy link

…Reference now, so the Reference is cleaned up nearly immediately

after freeing the last strong reference of the metaclass.

Prior it was used a SoftReference which prevents the ClassLoader, the ClassInfo and the Metaclass instances from beeing garbage-collected
until the JVM runs nearly into an OutOfMemoryException (PermGen). This leads to a JVM which is always near the maximum of memory usage.

…Reference now, so the Reference is cleaned up nearly immediately

after freeing the last strong reference of the metaclass.

Prior it was used a SoftReference which prevents the ClassLoader, the ClassInfo and the Metaclass instances from beeing garbage-collected
until the JVM runs nearly into an OutOfMemoryException (PermGen). This leads to a JVM which is always near the maximum of memory usage.
@paulk-asert
Copy link
Contributor

@blackdrag Any thoughts?

@blackdrag
Copy link
Contributor

From my POV this is no solution. We are using soft references, because in the past a weak reference gave the class free too fast leading to the runtime constantly recreating the meta class and thus to horrible performance. Also just using a SoftReference is not supposed to prevent the class to be unloaded. There are JVM configurations that behave like this though.
Of course @NecOnIce is fully right when he says that the current configuration leads the JVM to use up all memory before anything is freed.
Better would be a system in which we count how often we create the meta class and then maybe go with the strategy of creating first a weak reference and after a threshold has been reached to change it to a soft reference... just as an idea

@NecOnIce
Copy link
Author

Sry for my very late response. The behavior which constantly recreates the metaclass is really no suitable solution and i agree that my Request therefore is no solution as well.
The Problem where i have observed the behavior of using nearly the maximum amount of memory was an application which loads Strings out of a Database which represents Rules for calculating prices. These are loaded many times a hour. Each time a purchase was made, a request is fired against the database and a String is evaluated. For each such request Groovy creates a new script class and a corresponding metaclass. I was able to free the created Script classes but not the metaclasses. I think the Problem here lies in the fact, that groovy can't know if it should keep the metaclass for later recreations or not ... Could it be possible to manually free all metaclasses of a GroovyShell by calling a method on it? Like the resetLoadedClasses() method? So as a programmer i'm able to free specific metaclasses this way?

@blackdrag
Copy link
Contributor

But the metaclass has hard references on the class it is a metaclass for I thought. Therefore it should be impossible to unload the classes without also or first unloading the meta classes.

The usual approach is to actually create a cache for compiled scripts and avoid the creation of the classes again and again. From what I understood in your case it can happen that you have, over a session, just two many different rules as scripts, so that this is not possible.. Which would mean you have ten thousands of them... Is that right?

@NecOnIce
Copy link
Author

I haven't ten thousands of Rules in my Application, just about 100. Which are stored as Strings inside a Database Table. These are loaded by a request and than evaluated by a GroovyShell. I have noticed, that for a particular Rule there is created each time a new Script instance.

I have attached some Screenshots of my MAT Analysis. There are instances with name Script36170, ... so there multiple ten thousands of instances.

Is it possible, that some specific contents of the String which is parsed to a class could cause such a problem? like a Closure inside the String?
HDump_analysesClassloaderGCRoot
HDump_analysesGroovyClassLoaderInstances

@blackdrag
Copy link
Contributor

@NecOnIce I know this has been a long time... is this issue actually still a problem today?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants