Conversation
|
Any way you can add a test that would have failed before? |
There was a problem hiding this comment.
Is key always of java.lang.Class type?
If it is always a java.lang.Class, can you please use #getName() instead of #toString() as it would avoid producing java garbage?
Can you please add relevant comment explaining why you avoid using key as a, well, key?
That would make the intention clear for other developers who happen to touch this code later.
|
Added a test case and improved the fix. |
|
Went back to the key.toString approach. The way keys are being generated should produce unique string representations. The problem comes because the key holds references to the callbacks of the enhanced class that may hold references to whatever the callback needs to do. That reference in the callback, being referenced by the key is what pevents those classes from being unloaded. By getting the string from the key and not using it for anything else prevents these unwanted references from staying in the cache. Also, with the previous WeakHashMap approach, the cache entry would be wiped out by any GC run, defeating its purpose, that's why i went back to the key.toString approach. |
There was a problem hiding this comment.
It can be faster if you just test that a single classloader gets unloaded via PhantomReference<ClassLoader> -> ReferenceQueue.
No need to wait for OOM, you just need to test that a single classloader can be unloaded.
Why not |
Let me put that in another way: what will happen if two keys would accidentally happen to have the same |
There was a problem hiding this comment.
Please use spaces, not tabs for indent
|
From what i could see in the code, the toString in the keys are build with the same information that is used for equals and hashCode, all referenced classes being put as fully qualified. Anyway, I'm open to suggestions as long as the classloader leak issue can be fixed. Thanks, |
|
What if use |
|
I tried that approach, but the problem there would be that a CG run will remove the cache entry since the key is a "normal" object and not something that goes in PermGen. That would happen to often for the cache to be effective as a cache. |
|
What if the key itself would hold a weak reference to the class? |
|
The problem is that the reference from the key is not to a class, it is (in this case) to the aspected object. If that were done weak, garbage collector could remove it anytime and that would reduce the efficiency of the cache. |
|
Does this aspected object hold a reference to the class? |
|
The aspected object is an instance of the class loaded by the same classloader that the enhaced class is being generated in. I don't think a weak reference there would work, since it will eventually need to use the aspected object from the aspect generated with cglib. |
|
I found a way, as Vladimir pointed out before, to use the generated class name of the key instead of #toSting(). That change is pushed. I had to handle some cases where the key was a String already. |
|
I'll have a look in a couple of days. It is somewhat hard to validate without opening the code in IDE. |
|
@elrodro83 , I'm afraid, your fix relies on the fact "hashCodes never collide" which is apparently false. |
|
@elrodro83 , see my approach to tackle the problem: #50 |
|
@vlsi looking at your code, and testing with the stressHashCode property, i see that calls to getClassName may not be idempotent. |
|
Just looked at it, that's fine by me it it gets the fix for the leak. I'll close this PR and continue in #50 |
The key object put in the cache may be an instance of a dynamically generated class that references an application classloader. That reference causes said classloader to not be available for garbage collection, thus leaking the PermGen with old classes when that classloader is not needed anymore. This is mostly experienced in application restart scenarios, where each application has its own classloader managed in a long-lived container.
Attached is an exceprt from a heap dump that shoes the reference to the classloader that causes the issue: