Build Best Practices to avoid Classloader leaks - OutOfMemoryError: PermGen space - maven

I was reading some post around here about OutOfMemoryError: PermGen space. This one here took a special attention. Dealing with "java.lang.OutOfMemoryError: PermGen space" error
Also, this same post mentions other web references
http://frankkieviet.blogspot.ca/2006/10/classloader-leaks-dreaded-permgen-space.html
http://frankkieviet.blogspot.ca/2006/10/how-to-fix-dreaded-permgen-space.html
As far as I understood the ClassLoader leak is, in some cases, associated with a deployment that have classes present inside the App ClassLoader which are beeing referenced from outside the App ClassLoader. The links in this posts illustrates an example, a Custom log Level.
Said that, my doubt is about Best Practice for Builds and Dependency Management. I use Maven and Bill of Materials with dependency analysis to check if I am not generate a package with more than I need. So far, so good. But I know that there is a precedence of Class Loader. In my case I use JBoss AS / WildFly that uses the UnifiedClassLoader.
In that case should I take in consideration that a WAR file built with Maven and BOM may have the same behavior as the example of the Logger? Is it still recommended to use BOM?

Related

Spring AOP with AspectJ - Load time weaving doubts

Reading the Spring AOP documentation (link), I'm having a hard time (maybe also because english is not my native language) understanding these paragraphs.
First, I read
Further, in certain environments, this support enables load-time
weaving without making any modifications to the application server’s
launch script that is needed to add
-javaagent:path/to/aspectjweaver.jar or (as we describe later in
this section)
-javaagent:path/to/org.springframework.instrument-{version}.jar
(previously named spring-agent.jar).
And
Developers modify one or more files that form the application context
to enable load-time weaving
Which files? #Aspect classes and aop.xml files?
Then, when describing an example in the same sub-chapter, they say
We have one last thing to do. The introduction to this section did say
that one could switch on LTW selectively on a per-ClassLoader basis
with Spring, and this is true. However, for this example, we use a
Java agent (supplied with Spring) to switch on the LTW. We use the
following command to run the Main class shown earlier:
And they apply a Java Agent to the JVM.
-javaagent:C:/projects/foo/lib/global/spring-instrument.jar
Now I have a couple of doubts.
If I #EnableLoadTimeWeaving, do I need the spring-instrument Jar file as Java Agent?
I suppose the answer is yes, because we need to add bytecode to the class file before loading it. But a confirmation would be much appreciated.
The Jar naming is a little ambiguos, first they mention spring-agent.jar, then they use org.springframework.instrument-{version}.jar, and then spring-instrument.jar.
Are we always talking about the same Jar file?
I see from another question you asked that you are using Spring Boot and running a fat jar. In this case you don't need #EnableLoadTimeWeaving or spring-instrument (formerly known as spring-agent). Just ignore them if you are not running in an appserver for which you don't control the agent path.
I opened an issue for you about the confusion in the docs: https://github.com/spring-projects/spring-framework/issues/22429.

Why is load time weaving using aspectjweaver javaagent so slow for me?

The project I'm working on is considerably large. While trying to get load time weaving working for this spring project, I was instructed to use both the spring-instrument javaagent as well as the aspectjweaver javaagent. However, I notice that when using the aspectjweaver agent, my launch time shoots up 4-6 fold. I can also see identical weave messages 4-6 times coming from ContextOverridingClassLoader.
If I remove aspectjweaver however, and only use spring-instrument, I notice my launch time decrease dramatically with only a single weave message per join point coming from AppClassLoader.
The only issue being that some specific classes are not woven (I found that this is due to the spring application context not yet being loaded before the faulty classes are loaded by the class loader, as spring is the mechanism that enables the weaving). I've found a solution of my own by creating a custom javaagent which enables weaving in the same manner that spring-instrument does, only it does so in the premain rather than on application context load. It now weaves all the classes and in reasonable time.
However, I'd prefer not to go down this hacky road as I can only presume that the two agents were designed the way it is for a reason.
I wonder if anyone else has seen a similar issue with the aspectjweaver javaagent and if someone might know why that agent is so slow compared to just using spring-instrument.
If the answer interests anyone, I've figured out the issue.
Spring uses a temporary classloader ContextOverridingClassLoader to get metadata about the bean classes prior to actually loading them into the context.
The spring-instrument javaagent (or more accurately, the spring framework code which may or may not use the spring-instrument javaagent) specifically only weaves classes loaded by the classloader used to load the application context.
Code inside of InstrumentationLoadTimeWeaver$FilteringClassFileTransformer:
if (!this.targetClassLoader.equals(loader)) {
return null;
}
return this.targetTransformer.transform(
loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
On the other hand, aspectjweaver does not have such a filtering mechanism and so will weave even those classes loaded by spring's temporary ContextOverridingClassLoader. Fortunately, aspectjweaver has an essentially undocumented system property (or at least I was unable to find any documentation on this) called aj.weaving.loadersToSkip. By setting this to:
-Daj.weaving.loadersToSkip=org.springframework.context.support.ContextTypeMatchClassLoader$ContextOverridingClassLoader
I was able to skip weaving for that classloader and speed up the loading of my application context tremendously.
Incidentally, I've found that both the spring-instrument and aspectjweaver ultimately both use ClassPreProcessorAgentAdapter to weave the classes, and thus it is probably not necessary to use both agents (aspectjweaver will weave a superset of the classes that spring-instrument will). However, depending on your configuration, the application might complain about the missing agent at startup so you might as well include it (at the cost of some additional unnecessary overhead).

Classpath scanning in OSGi

My project has a set of custom defined annotations that could be present in any bundle deployed in the OSGi 4.3 framework. I want to find any class with these annotations in the classpath. I tried using BundleWiring.listResources(...) and Bundle.loadClass(...) for each class found. I have done some tests with an small set of bundles and it needs almost 200MB of Permanent Generation JVM memory space because all classes are loaded.
Is there a way to free loaded classes PermGen memory space when the program realizes that they does not have these annotations?
Is there a better way to look for annotated classes in an OSGi framework?
I think you should not do annotation scanning as it slows down startup and needs a lot of memory. JEE application servers do annotation scanning at startup to make lazy programmers happy and the result is very annoying (e.g. scan for JPA or EJB annotations).
I guess you are implementing a technology where you can define the rules. I suggest that you should define rules that are similar to these:
Annotate your class
Have a MANIFEST header where the annotated class must be listed.
An even better solution can be to use a custom capability namespace with specified attributes. E.g.:
Provide-Capability: myNamespace;classes=com.foo.myClass1,com.foo.myClass2
In your technology, you should write a BundleTracker that calls:
BundleWiring.getCapabilities("myNamespace");
If the namespace is present, you can find the classes that should be processed.
If you implemented the technology, you can consider an extension to Bnd to fill that MANIFEST header automatically. That extension can be used than when bnd is started from the command line or from build tools like maven.
Btw.: You can use ASM to parse the class bytecode or use the built in possibility of Java to build up AST. Although those could work to solve the memory issue, I still think that you should define the list of classes directly in the MANIFEST header as it makes things much more clear. You can read the MANIFEST headers, you can check the capabilities on webconsole but you cannot do the same with bytecode.
Usually, classpath scanning for annotations is a bad idea in an OSGi context, as the classpath is more like a graph. However, there are situations where this can be useful. Hence, OSGi encourages the usage of the Whiteboard Pattern.
What you could possibly do is register each of these classes as services in the OSGi registry. Then, create a separate bundle that just tracks these services and transforms/manipulates them in some way. For example, this project scans for all classes annotated with #Path and #Provider annotations, and transforms them into Jersey REST APIs.

Large portlet war takes up memory causing performance issues?

I have heard a few people say that deploying a portlet war file (or perhaps any war) that includes a lot of large jars can cause performace issues because all those jars get loaded into memory. If you have several wars, all of which include a ton of large jar files, your system will get bogged down.
I'm trying to get my head around why this is true - and I haven't found anything that explains it in a way that I get it. Maybe I'm searching for the wrong terms which is why I'm not finding much information. Can anyone explain what exactly is happening when a portlet gets instantiated and if indeed those jars start taking up memory?
The short response is: yes, deploying a war file with a lot of jars "could" cause a performance issue. It does not matter if the war contains a portlet or a standard web application.
But in my opinion you should not worry about this prematurely, because there are easy solutions for this problem.
When a portlet or any webApp is loaded into the server it loads the classes of the main jar into the "Permanent generation" region of the heap (memory assigned to the Java process) of the web server. This region stores the code that is executed. When these classes use code from other jars, their code is also loaded into this region.
If this regions is filled up, you will get an OutOfMemoryError exception.
The solutions for your problems are easy:
Dedicate more memory to your memory (parameter -Xmx of the JVM)
If you have several .war files with the same jar files in them, remove those jars from the war files and put them in the directory where all the common libraries of the Web Server are located. The location of this directory depends on the Web App server that you are using.
So, you should not worry about this problem because it has a solution.
This PDF Memory Management in the JavaHotSpotâ„¢ Virtual Machine explains how memory management works in Java. It applies to regular Java apps and Web applications.

How do you share Java Caching System (JCS) resource across multiple EJB

I am using JCS to store the ldap search results which should be shared by multiple EJB. I have created a singleton class to initialize JCS only once but due to EJB's classloader, it's been initialized multiple times with its own copy. so search resources are not shared.
How are you guys resolving issue where you need to share the cache across multiple beans?
I am looking for cache within JVM. (Not the remote e.g memcached etc.).
Glassfish is used as an application server.
I haven't been able to test it yet, but I think that one of the techniques explained in the "Circumventing Class Loader Isolation" chapter of the Application Development Guide for the version of Glassfish you are using may solve you problem.
Short version, at least valid for versions 2-3-4 : use the Common Classloader (what exactly this common classloader does and its relation to the other classloaders is explained in the same manual). There are several ways to do this:
copy the jar to domain-dir/lib
or copy the jar to as-install/lib
or run asadmin add-library --type common /path/to/your.jar (will only work in version 4 iirc)
There are several questions here on SO that are related to "Circumventing Class Loader Isolation" (just use that search term), look there for examples and more discussion.
Simply put, the singleton will likely "live" where your caching implementation class lives, as that's the classloader in the hierarchy that "owns" the class.
So, if each EJB is separately deployed, with their own copy of the cache lib jar, they'll each get their own copy.
If your beans are deployed in a composite EAR, sharing a single instance of the lib jar, then that cache will be shared across the beans in the EAR.
If you remove the lib from the deployment completely, and put it outside the container ($DOMAIN/lib/ext for example), then that cache will be shared by EVERYTHING in the domain (EJBs, EARs, WARs, etc.).

Resources