Is there a way to determine which classes are loaded from which JARs at runtime?
I'm sure we've all been in JAR hell before. I've run across this problem a lot troubleshooting ClassNotFoundExceptions and NoClassDefFoundErrors on projects. I'd like to avoid finding all instances of a class in JARs and using process of elimination on the code causing a CNFE to find the culprit.
Will any profiling or management tools give you this kind of information?
This problem is super annoying purely because we should have this information at the time the class gets loaded. There has to be a way to get to it, or record it and find it, yet I know of nothing that will do this, do you?
I know OSGi and versioned bundles/modules aim to make this a non issue... but it doesn't seem to be going away any time soon.
Note: I found this question is a subset of my question related to classes loaded from versioned jars.
Somewhat related, this post explains a strategy to search for a class within JARs (either under the current directory) or in your M2_REPO: JarScan, scan all JAR files in all subfolders for specific class
Also somewhat related, JBoss Tattletale
Passing the -verbose:class switch to the java command will print each class loaded and where it was loaded from.
Joops is also a nice tool for finding missing classes ahead of time.
From code you can call:
myObject.getClass().getProtectionDomain().getCodeSource()
(Note, getProtectionDomain may unfortunately return null (bad design), so "proper code" would check for that.)
There is an MBean for the JVM flag mentioned by Jason Day above.
If you are using JBoss, you can twiddle this on demand using JMX, if you add the native JMX MBean server to your config. Add the following -D's:
-Dcom.sun.management.jmxremote.port=3333
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djboss.platform.mbeanserver
-Djavax.management.builder.initial=org.jboss.system.server.jmx.MBeanServerBuilderImpl
-DJBOSS_CLASSPATH="../lib/jboss-system-jmx.jar"
And then you can see this setting under the java.lang:Classloading MBean and can cut it on/off on the fly. This is helpful if you only want it on while executing a certain piece of code.
There is also an MBean which will allow you to enter a fully qualified classname and see where it was loaded from in the class hierarchy. The MBean is called LoaderRepository and you'll want to invoke the displayClassInfo() operation, passing in the FQCN.
In WebSphere (WAS) you can use a feature called "Class Loader Viewer"
Enable the class loader viewer first by clicking Servers > Server Types > WebSphere application servers > server_name > Class loader viewer service, enable the service and restart the server.
Then you can go to Troubleshooting > Class Loader Viewer and searching for your class or package name.
https://www-01.ibm.com/support/knowledgecenter/SSAW57_8.5.5/com.ibm.websphere.nd.doc/ae/ttrb_classload_viewer.html?lang=en
You can easily export a JMX operation to access package info for any loaded class in you process like:
public static final class Jmx {
#JmxExport
public static Reflections.PackageInfo getPackageInfo(#JmxExport("className") final String className) {
return Reflections.getPackageInfo(className);
}
}
and here is a simple unit test to export and invoke it:
#Test
public void testClassLocator() throws IOException, InstanceNotFoundException, MBeanException, ReflectionException {
Registry.export(Jmx.class);
Reflections.PackageInfo info = (Reflections.PackageInfo) Client.callOperation(
"service:jmx:rmi:///jndi/rmi://:9999/jmxrmi",
Jmx.class.getPackage().getName(),
Jmx.class.getSimpleName(), "getPackageInfo", Registry.class.getName());
System.out.println(info);
Assert.assertNotNull(info);
}
this is all based using some small utilities library from spf4j (http://www.spf4j.org)
you can see this code at and the test at
Related
I faced with the problem:
Native Library Ltkrnx.dll already loaded in another classloader
during redeploy application(tomcat 8 server).
I also added check, but it's doesn't help me.
private void loadLibrary(LTLibrary library) {
if (!Platform.isLibraryLoaded(library)) {
Platform.loadLibrary(library);
}
}
Caused by: leadtools.RasterException: Native Library C:\LEADTOOLS 20\Bin\CDLL\x64\Ltkrnx.dll already loaded in another classloader
Are you using LEADTOOLS in 2 different web applications? If yes, the following answer might help you solve the problem:
java.lang.UnsatisfiedLinkError: Native Library XXX.so already loaded in another classloader
Since that question is about OpenCV, not LEADTOOLS, I will quote the relevant parts here (very slightly edited):
Now there's the restriction that a native library can only be loaded
in one class loader. Web applications use their own class loader so if
one web application has loaded a native library, another web
application cannot do the same. Therefore code loading native
libraries cannot be put in a webapp directory but must be put in the
container's (Tomcat) shared directory. When you have a class written
with the usual pattern above (loadLibrary in static initializer of
using class) it's enough to put the jar containing the class in the
shared directory. With .. the loadLibrary call in the web application
code however, the native library will still be loaded in the "wrong"
class loader and you will get the UnsatisfiedLinkError.
To make the "right" class loader load the native library you could
create a tiny class with a single static method doing only the
loadLibrary. Put this class in an extra jar and put this jar in the
shared Tomcat directory. Then in the web applications replace the call
to System.loadLibrary with a call to your new static method. This way
the class loaders for the .. native library will match and the native
methods can be initialized.
If your situation is different, or the suggestion there doesn’t help you, send the following information to support#leadtools.com and our support team will work with you to isolate the problem:
The details of this question (exception you’re getting, version 20 of LEADTOOLS, 64-bit, Tomcat 8)
Your LEADTOOLS product serial number (don’t post it here!). If you’re still evaluating and don’t have a serial number, just mention that.
What you’ve tried so far to solve the problem and what results that gave you (for example, the answer mentioned above).
Other details about your OS, IDE or programming environment in general.
I'm aware that by using the flag verbose:class, we can get the jvm to log out when a class is loaded and from where. However, I want to see some additional information - which class loader loaded the class, and ideally the class which was being executed that caused the loading. (Not entirely sure that latter part even make sense!)
Is there any way to get the jvm to log this info, or any other suggestions of how to get it? Thanks
You can see what triggered a class load in some cases if you use -XX:+TraceClassLoading and -XX:+TraceClassResolution you'll see a collection of Loading messages (when the .class bytes get loaded) and subsequent RESOLVE messages when the classes themselves get resolved. So by figuring out which RESOLVE messages you're seeing you should be able to determine which class is causing a dependent class to be loaded.
Unfortunately this doesn't tell you anything about your classloaders. So although it will print out the JAR that it's loading from, if that doesn't uniquely identify your classloader then it may not be possible to answer the question using standard tools. However, if you're using an embedded engine such as Tomcat or OSGi that provide their own classloaders, there may be additional debugging flags that you can turn on in order to identify which classloader instance is being used.
If your problem is debuging classloading I would consider using a debugger.
Using intellij i was able to set a breakpoint in the url-classloader.
You can configure this breakpoint to log a custom message instead of breaking.
If you want to be able to turn this on in production you could of course write your own classloader.
This isn't dificult, but you will have to figure out how to log to the logging framework without logging the loading of the loading framework. I guess the easiest way would be to ignore some predefined packages when logging.
If you choose this route I can probably provide you with a shell of a solution.
Just ask.
I have started an open source Scala project named omniprop. The feature I'm currently exploring is how to allow users of the project to stack JVM-styled property providers. For instance, you may wish to look up properties in java.lang.System, Lift's util.Prop, and Typesafe's Config library. Due to some other constraints/features of omniprop, I need this stack configuration to reside in a known object, so other parts of the library can retrieve properties from this stack.
In order for omniprop to work correctly, this configuration needs to be invoked by the user of the library before any properties are accessed. Hence any project which uses my library will need a bootstrap/initializer which can set up the provider stack. An example of this initial configuration code looks like this:
import com.joescii.omniprop.providers._
PropertyProviders.configure(List(
SystemPropertyProvider,
LiftPropsProvider
))
The challenge I'm facing is with testing in particular. In order for the test code for a project utilizing omniprop to work, it must somehow run the above code before any tests are run. Currently, I don't see a clean way to do this with sbt or any of the testing libraries I am familiar with such as scalatest, scalacheck, or specs2. As it is, one would need to call the above snippet in every test suite, which is certainly not ideal.
Another approach this this problem is what Lift does, in which every project necessarily has a class called bootstrap.liftweb.Boot that the library invokes to set everything up. I find that to be a reasonable approach to a web framework such as Lift, but seems to be too much for a tiny property helper library.
I really have two questions here:
How can I have sbt invoke the above setup code with the correct classloader before all tests run?
More importantly, is this the best design for a library which requires initialization, or is there a better approach?
Using ScalaTest, when I've had to do something similar, I created a trait that extends BeforeAndAfterAll, which I mixed into every suite that needed it.
trait Configure extends Suite with BeforeAndAfterAll {
override def beforeAll() { PropertyProviders.configure(/*...*/); }
override def afterAll() { PropertyProviders.configure(/*...*/); }
}
You just mix it in like any other trait
trait FooSpec extends Spec with Configure {
// ...
}
You could put the initialization code in a trait constructor and have your tests extend from that trait.
Another approach is to have that configuration as the default, and if no configuration is set then it gets used the first time your library code is called. That would cover both testing and non-testing scenarios.
A hybrid approach would be to have your sbt testing configuration set a system property. If that system property is set and no configuration is has been set then the testing config will be used the first time the library code gets called.
I'd like to use something like the Filtering Classloader to prevent specific packages from creeping into the application context and becoming visible to Spring.
Changing the classloader order causes all sorts of nasty problems so I´d like to try this route.
Is it possible to achieve this with Websphere 6? If not, can I replace my own application classolader and implement the filter myself?
There is no such filtering mechanism in WebSphere, and there is no way to replace the application class loader. You'll have to use PARENT_LAST to override classes, sorry.
bkail's answer is right, WAS doesn't have such feature even in its latest public version (8.5.5).
I just created a RFE requesting such feature so whoever is interested in this, please vote for it which may increase the possibility of this being implemented:
http://www.ibm.com/developerworks/rfe/execute?use_case=viewRfe&CR_ID=43936
(IBM ID required)
In the meantime, you may use isolated shared libraries to override any particular classes (the above mentioned class loading order control - like parent_last - is too rough as it affects the class loading order of the whole application or module)
Create a shared library with desired jars on the classpath, configure it as isolated shared library, reference it from the deployed application (or module).
See here for complete documentation
http://pic.dhe.ibm.com/infocenter/wasinfo/v8r5/topic/com.ibm.websphere.base.doc/ae/tcws_sharedlib.html
I was just about to post the same question. But the answer was quite unsatisfying. I however checked the request from Petr H at the IBM developerworks and IBM did implement this feature (Huge thanks Petr!):
"WebSphere Application Server V8.5.5.7 (=Fixpack 7) gained the ability to prevent packages from the server classloader being visible to applications. This was delivered in the document "ISOLATE DEPLOYED ARTIFACTS FROM OSS PACKAGES" and is documented in 'Isolating open source software packages'.
The supplied links describe the mechanism by configuring always-protected packages. You basically have to do the following:
Under Server Infrastructure on the server settings page in the administrative console, click Java and process management > Process definition.
Select Java virtual machine.
Define the following system properties in the JVM generic arguments section as follows:
-Dcom.ibm.ws.classloader.server.alwaysProtectedPackages=org.bouncycastle.
Please not that the final dot "." is really important otherwise everything will be ignored! Several packages can be added by comma ","
Click Apply, OK and save the changes. Make sure that a file synchronization is done before you restart the servers. Restart WebSphere Application Server for the changes to take effect.
Examine the native_stdout.log and find the system properties that are previously defined. For example, when you specify always-protected package org.bouncycastle., statements such as the following might appear:
ProtectionMetaData.clinit: system property: com.ibm.ws.classloader.server.alwaysProtectedPackages=org.bouncycastle.
I wanted to add to my jdk6\jre\lib\security\java.policy file an interdiction to create some classes that are blacklisted by appengine. For example I want my local jvm to throw an exception when the application tries to instantiate javax.naming.NamingException.
It is possible?
I will try to explain my specific problem here. Google offers an service (GAE-google app engine) that has some limitations on what classes can be used. For example doesn't instantiate JNDI classes that are in javax.naming package. They also offer an testing server that can be used to tests this application on my machine, but this server allows such classes and can exacute the code. You find out that you used a blacklisted class only after you upload your application to google. I was thinking if such class blacklist enforcement couldn't be done on the development jvm. Else i'm thinking that this would be easy they might already provide such a policy file.
You could write a small loader application that creates a new, custom classloader. Your application classes could then be loaded using this classloader.
In the custom classloader, you can then throw ClassNotFoundException when your application tries to access a class that you want to blacklist.
You will need to overload the load() method. This method will be responsible for throwing the exception on your blacklisted classes ordelegating to the parent Classloader if the class is allowed. A sample implementation:
public Class loadClass(String name) throws ClassNotFoundException {
if(name.equals("javax.lang.ClassIDontLike")){
throw new ClassNotFoundException("I'm sorry, Dave. I'm afraid I can't do that.");
}
return super.loadClass(name, false);
}
(Of course, a real implementation can be way more sophisticated than this)
Because the classes of your application are loaded through this Classloader, and you are only delegating the loadClass() invokations to the parent classloader when you want to, you can blacklist any classes that you need.
I am pretty sure that this is the method that Google uses to blacklist classes in their server. They load every app in a specific Classloader. This is also similar to the way that Tomcat isolates the different Web Applications.
Wouldn't you rather get compilation errors than runtime errors while testing your program? You could configure your IDE or compiler to warn you when an undesired class is instantiated. I know AspectJ has some nice features for this: You can define compilation warnings/errors on join points and get feedback in e.g. Eclipse. To use this in Eclipse, you simply install the AspectJ plugin and write a suitable aspect. To get the errors while compiling from a command line or script, you would actually have to use the AspectJ compiler, but I doubt that you would need that.
The Java documentation lists all possible policy permissions here:
http://java.sun.com/javase/6/docs/technotes/guides/security/permissions.html
Class creation / loading is not mentioned, so I believe you cannot enforce this using a policy.
At any rate, why do you want to throw an exception when an exception class is loaded? Maybe you could explain your problem, then someone might be able to propose a solution.
Edit:
One way to prevent loading of certain classes would be to remove them from the JRE installation. Most system classes are contained in rt.jar in your JDK/JRE installation. You should be able to modify it with any ZIP-tool.
Just create a special installation of your JRE, and modify its rt.jar. That is an ugly hack, but should be OK for testing purposes...