I am struggling with a situation in which a ClassLoader is trying to resolve a resource, which only works under certain conditions.
The use-case is as follows: I am using IBM Rational Functional Tester in combination with JBehave for automated acceptance tests. JBehave specifies the tests as plain text story files. These story files can refer to other story files, so called "Given Stories". JBehave uses the ExecutorService to execute stories potentially multi-threaded. While JBehave has no problems to load the text files (with ClassLoader.getResourceAsStream), it fails finding the same files in the thread launched from ExecutorService.
The ClassLoader in action is the ContextFinder. When debugging the application, and suspending both threads, the "main thread" that originally started JBehave and the "story thread" launched from the executor service to run the story file, I can identify that the instance of the classloader is the same. Also the instances of the parents, etc.
But a call to
Thread.currentThread().getContextClassLoader().getResource("HelloWorld.story")
works perfectly in the main thread, and fails for the story thread and returns null.
Judging from the source code of the ContextFinder, it seems like it does little else then gathering all the ClassLoaders for the classes on the stack. So I tried this:
SomeClass.class.getClass().getClassLoader().getResource("HelloWorld.story")
... with the same result.
This is too strange for me. Any pointer for debugging or reasing why this behavior is showing is appreciated!
The thread context classloader (TCCL) is basically undefined in OSGi. You should avoid using it.
As an extension to standard OSGi, Equinox does supply this thing called the ContextFinder, which performs stack inspection to try to find the topmost OSGi bundle classloader in the call stack. However you get almost no control, and the result can be quite unexpected as you have seen. Of course since this is an Equinox-specific extension, any code that relies on ContextFinder working properly will fail on all other OSGi Frameworks.
So, rather than wasting time trying to debug this, it's better just not to use the TCCL at all. If you want to load a resource relative to a specific class, then do it from the literal class object, e.g.:
MyClass.class.getResource("HelloWorld.story");
UPDATE:
I noticed this in your original question: SomeClass.class.getClass(). The result of this will be the class-object of java.lang.Class itself. Calling getClassLoader() on that will always return the JVM boot class loader.... probably not what you intended!
Related
Is it possible to dynamically instrument Java bytecode without a Java agent? I have instrumented bytecode using a Java agent before, doing something akin to this:
ClassFileTransformer myTransformer = new Transformer();
instrument.addTransformer(myTransformer, true);
instrument.retransformClasses(classInstance);
instrument.removeTransformer(myTransformer);
But is this possible without the use of a Java agent? What I would like to do is call a method which will do my instrumentation at any given time after the JVM is running, just without the use of an agent.
The only ways to perform byte code transformation without an instance of an Instrumentation implementation would be
Custom class loaders which can change the bytes before calling defineClass (which is limited to classes loaded through that loader)
Calling MethodHandles.Lookup.defineClass with modified bytes even before the class has been loaded, which works on the widespread JVMs with lazy loading, but is limited to your own module or modules opened to your module
Neither approach can change already loaded classes. That requires the Instrumentation reference and the only place where a JVM ever hands out such reference, are the initialization methods of Java Agents. So to use it, a Java Agent is unavoidable, even if it may be just a stub storing the reference, for use by your application code.
Note that starting with Java 9, there is the Launcher-Agent-Class manifest attribute for jar files that can specify the class of a Java Agent to start before the class specified with the Main-Class is launched. That way, you can easily have your Agent collaborating with your application code in your JVM, without the need for any additional command line options. The Agent can be as simple as having an agentmain method in your main class storing the Instrumentation reference in a static variable.
See the java.lang.instrument package documentation…
Getting hands on an Instrumentation instance when the JVM has not been started with Agents is trickier. It must support launching Agents after startup in general, e.g. via the Attach API. This answer demonstrates at its end such a self-attach to get hands on the Instrumentation. When you have the necessary manifest attribute in your application jar file, you could even use that as agent jar and omit the creation of a temporary stub file.
However, recent JVMs forbid self-attaching unless -Djdk.attach.allowAttachSelf=true has been specified at startup, but I suppose, taking additional steps at startup time, is precisely what you don’t want to do. One way to circumvent this, is to use another process. All this process has to to, is to attach to your original process and tell the JVM to start the Agent. Then, it may already terminate and everything else works the same way as before the introduction of this restriction.
As mentioned in this comment, Byte-Buddy has already implemented those necessary steps and the stripped-down Byte-Buddy-Agent contains that logic only, so you can use it to build your own logic atop it.
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?
I have a large spring project, using xml configuration. I'm looking for a quick way to verify changes to the xml configuration.
I can load the whole project locally - the problem is this takes more than 5 minutes, loads a huge amount of data.
My XML editor catches XML formatting errors.
I'm looking for something intermediate - to catch obvious problems like references to beans that aren't defined, or calling constructors with the wrong arguments. Is there a quick way to do this, without having to actually invoke all the constructors and bring up the whole environment?
I'm building with Maven and editing with Eclipse, although my question isn't specific to either.
Since you already use Eclipse, you could try Spring Tool Suite (comes either standalone or as an add-on). It's essentially Eclipse with extra Spring-specific features, like Beans Validator. I'm not sure how thorough the validation is, but it should catch most configuration problems.
It's maintained by SpringSource so its integration with Spring "just works" and it's guaranteed not be more or less in sync with Spring Framework's release cycle.
Beanoh :
http://beanoh.org/overview.html#Verify
this project does exactly what I'm looking for. Verify obvious problems with spring config, but without the overhead of initializing everything.
You can use a Spring testing support to integration test your Spring configuration. However if the loading of the context is taking 5 mins, then the tests will also take the same amount of time. Spring does cache the context so if you have multiple tests using the same set of Spring contexts, then once cached the tests should be very quick.
I can suggest a few ways to more efficiently test your configuration:
Organize your project in modules, with each module being responsible for its own Spring configuration - this way, each module can be independently developed and tested.
If you have a modular structure, the testing can be more localized by mocking out the dependent modules, again this is for speed.
I would like to know what is "Activate this plug-in when one of its classes is loaded" check-box in Eclipse manifest editor useful for.
I thought Eclipse always use "lazy initialization" approach. Does have this option a relation to the BundleActivator class of the plugin? is initialization something different to activation?
Here is a similar question, but I don't understand it entirely.
Ticking the box causes the following header to be set in the manifest:
Bundle-ActivationPolicy: lazy
I'll start with how "pure" OSGi deals with this. IF the bundle is started with the START_ACTIVATION_POLICY flag then the bundle enters the STARTING state but the activator's start() method is not invoked and a ClassLoader is not allocated for the bundle. The bundle stays in STARTING until, for whatever reason, a class needs to be loaded from the bundle. At that point a ClassLoader is allocated and the activator (if any) is instantiated and its start() method is invoked before the requested class is loaded.
However Eclipse layers additional semantics on the top. As background, Eclipse always tries to avoid starting bundles in order to keep its start-up time minimal. A very small core set of bundles is started by default (the list is in configuration/config.ini) and one of these is called the p2 "simpleconfigurator". The simpleconfigurator looks for bundles that have the Bundle-ActivationPolicy:lazy header and it starts them with the START_ACTIVATION_POLICY flag... therefore these bundles will be "lazily" started as described above.
The important point is that all other bundles that do not contain the header will not be started at all under Eclipse. They will stay in RESOLVED state, their activators will not be invoked, and if they contain any Declarative Services component they will not be loaded. This is because Declarative Services only ever looks at bundles that are in ACTIVE or STARTING state.
Therefore the main reason to use the header is if we want to write a bundle containing Declarative Services components that need to work under Eclipse.
In other environments there is no need to use the header. Most normal OSGi apps simply start all bundles, rather than trying to selectively start a subset of bundles. Note that this doesn't mean OSGi apps don't worry about lazy loading! Declarative Services already supports lazy loading without messing around with bundle class loading triggers. In my opinion Eclipse gets this wrong and has added unnecessary complexity to the bundle lifecycle. Nevertheless if you are running in Eclipse then you have no choice but to understand and work with its limitation.
The integration test classes generated for me by Grails when I created my domain classes do not extend the class GroovyTestCase. However, I have seen it recommended by many authors (here is an example in order to use the shouldFail method, which indeed seems to work).
However, extending my test class from GroovyTestCase has resulted in the following error message when I run test-app in the interactive Grails console:
Spring Loaded: Cannot reload new version of foo.barTests
Reason: Supertype changed from java/lang/Object to groovy/util/GroovyTestCase
Is this something I should be concerned about? I have searched online and cannot find other people complaining about this error, so it might be something new with Grails 2.2. Please advise.
I am running my tests in the grails interactive console (what you get when you run grails without arguments). I've left my tests inheriting from Object for a while, but when I run test-app I still occasionally get those messages output to the HTML test report (of the "changed from GroovyTestCase to Object" variety).
I am quite sure it's a Grails bug related to
AST Transformation annotations
spring-loaded module
As I've encountered this strange behaviour as well.
The steps that caused this problem seem to be that a Groovy class is compiled once without transformation, so that it's a subclass of java.lang.Object.
When the AST transformaton kicks it, the class is recompiled again. This time, it becomes a subclass of another class. Then Spring-loaded fails to re-load them into the memory (as JVM does not allow the same class to redefine its super class).