java.lang.ClassNotFoundException while instrumenting eclipse rcp application - java

I tried injecting a method call statement using javassist in every method of some desired classes. The statement corresponds to a class in the java-agent jar. For example if my agent has class like a.b.HelperClass, I am injecting a.b.HelperClass.call(); in the beginning of every class using javassist.
I tried with a spring boot web app and the agent works fine but with RCP application it is throwing
java.lang.ClassNotFoundException: a.b.HelperClass
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:506)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:422)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:410)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
Do I need to load the classes residing inside agent-jar using the eclipse class loader? BTW I'm instrumenting by calling agent-main method and not premain.

Eclipse is OSGi based and has a module system that is enforced.
The HelperClass must be in the classpath of the Eclipse Plugin where it should be used.

Related

JNI NoClassDefFoundError in springboot executable jar

I have springboot application which is connecting to client shared dynamic library using jni.
There is one **callback method **which is registered to dll using ine register function.
This method is invoked on some events from dll.
When executed as java application from intellij, this works fine but when executed **as jar **and when this callback method is invoked its throwing **NoClassDefFoundError ** as below
java.lang.NoClassDefFoundError: com/test/Sample
Caused by: java.lang.ClassNotFoundException: com.test.Sample
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java: 424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
By default springboot puts all classes inside BOOT-INF folder.
When I manually modified jar and added this class outside BOOT-INF i.e at rootLevel it worked.
Like below:
BOOT-INF
com
META-INF
org
In above snippet com is directory inside which Sample class was present under subpackage test.
springboot version used: 2.3.6.RELEASE
Using springboot-maven-plugin to create executable jar

Using javaagent with javassist in WildFly

I've written a simple javaagent that basically injects some logging in classes that are part of the JDK, such as javax/imageio/spi/ServiceRegistry, using javassist.
It works fine in a simple standalone application, but I cannot get it to work in WildFly 10. What I have tried:
Added the agent JAR as a module to WildFly along with the corresponding module.xml which declares <module name="org.javassist"/> as dependency
Appended the agent package and org.javassist to JBOSS_MODULES_SYSTEM_PKGS
Appended -javaagent:/full/path/to/agent/jar/in/module to JAVA_OPTS
WildFly starts but in server.log I get:
java.lang.NoClassDefFoundError: javassist/ClassPool
at net.luniks.agent.LoggerChanger.transform(LoggerChanger.java:48)
at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:428)
at java.lang.ClassLoader.findBootstrapClass(Native Method)
at java.lang.ClassLoader.findBootstrapClassOrNull(ClassLoader.java:1015)
at java.lang.ClassLoader.loadClass(ClassLoader.java:413)
at java.lang.ClassLoader.loadClass(ClassLoader.java:411)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at org.jboss.modules.ClassLoaderLocalLoader.loadClassLocal(ClassLoaderLocalLoader.java:74)
at org.jboss.modules.Module.loadModuleClass(Module.java:606)
at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:190)
It seems the module class loader is used but even though the agent module has a dependency to org.javassist, it still cannot load its classes.
What am I missing?
Eventually I got it to work by adding only the package of the agent to JBOSS_MODULES_SYSTEM_PKGS (not "javassist") and adding the org.javassist module JAR to the boot classpath:
JAVA_OPTS="$JAVA_OPTS -Xbootclasspath/p:/path/to/wildfly/modules/system/layers/base/org/javassist/main/javassist-3.18.1-GA.jar"
Now the agent works, it can load the Javassist classes. Certainly not the clean way but it is just for debugging purposes...

Hibernate java.lang.ClassCastException: _$$_javassist_856 cannot be cast to javassist.util.proxy.Proxy when using Websphere Shared Library

Websphere 8.0.0.11
Hibernate 4.2.21.Final
I have found many questions about this same problem but none of them worked for me.
If I deploy the application in Websphere it works OK.
However we have defined a shared library that contains all the third party libraries (spring, hibernate, javassist, etc) so that our WARs are thinner.
This way during deployment we associate our thin WAR against that Websphere shared library.
The point is that when we deploy the application this way the ClassCastException Hibernate exception _$$_javassist_856 cannot be cast to javassist.util.proxy.Proxy is thrown.
I have checked the loaded jars in the websphere console and can only see one javassist jar (3.18.1-GA) in the classpath.
Why could this be happening?
UPDATE
I have also tried using PARENT_FIRST and PARENT_LAST class loading.
UPDATE 2
I just found out that Websphere is loading its own javassist jar:
URL location = ProxyFactory.class.getProtectionDomain().getCodeSource().getLocation();
logger.info("{}", location);
It prints: file:/opt/IBM/WebSphere/AppServer/plugins/javassist.jar
After trying pretty much everything I found on S.O. without any success I decided to downgrade Hibernate to version 4.1.12.Final. This is the maximum 4.x version compatible with Websphere 8.x.
The problem is that Javassist leaves traces in its generated code. With Javassist on the class path twice, its classes are loaded twice. Two types are however only equal if they have the same name and are loaded by the same class loader. In your case, the generated class resolves its Javassist dependeny to a type that is loaded by your application class loader while your code is casting the instance to the Javassist type that is loaded by the Websphere class loader (or the other way around).
Are you sharing any Hibernate dependencies between applications? Try to not use any shared libraries related to Hibernate in your application to avoid this.

Referencing an external class from a Jersey REST web app

I am trying a simple example of creating a RESTful API. I used the Maven jersey-quickstart-webapp archtype to create a Jersey web app. In a separate project I created a simple class: SimpleClass, which only has one method that returns "hello". I am trying to create an instance of that class in my method in the web app (I am using the default MyResource class) and call its method to get "Hello". I exported the project with the SimpleClass to a JAR file, and added that file to the build path for my Jersey project, and imported the relevant package.
When I run the web app on a local server, and call the MyResource method, I get an error with the root cause (just the top few rows):
java.lang.NoClassDefFoundError: Lorg/test/simple/SimpleClass;
java.lang.Class.getDeclaredFields0(Native Method)
java.lang.Class.privateGetDeclaredFields(Class.java:2583)
java.lang.Class.getDeclaredFields(Class.java:1916)
So, it can't find the SimpleClass class.
What am I doing wrong here? I'd really appreciate any help!
Thanks,
Yariv.
New info: I tried to create a RESTful web service without Maven. I successfully created the project with a simple "Hello World" example, and then I tried to add my own class from another project: I imported the .jar, added it to the build path, and created a class in the web service that creates an instance of my class when a GET is made to the server. My class happens to include (as members) instances of other classes, one of which connects to a MongoDB database, and when I run the service, I again get a HTTP 500 error as follows:
A MultiException has 2 exceptions. They are:
1. java.lang.NoClassDefFoundError: com/mongodb/DBObject
2. java.lang.IllegalStateException: Unable to perform operation: create on org.notes.server.NotesServer
Adding the MongoDB jar to the web project did not help. I must be missing something big here. What should I do to call code I created in another project (with a set of dependencies there) in my web service?
I'll appreciate any help I can get, I am getting nowhere with this...
I was able to resolve all these issues by adding all the relevant JARs to the deployment assembly (right-click on the project, click Properties, then select Deployment Assembly and add all the JARs that my class depends on, as well as its own JAR).
Thanks for your help, radai!

Vaadin/OSGi : ScssStylesheet class not found

I use vaadin and OSGi to create a modular application. After a long fight, I was able to deploy successfully the application. However, I can't load the style. When I try to access to
http://localhost:8080/myapp/VAADIN/themes/myTheme/styles.css
I got the following exception:
exception
javax.servlet.ServletException: Servlet execution threw an exception
root cause
java.lang.NoClassDefFoundError: com/vaadin/sass/internal/ScssStylesheet
com.vaadin.server.VaadinServlet.serveOnTheFlyCompiledScss(VaadinServlet.java:957)
com.vaadin.server.VaadinServlet.serveStaticResourcesInVAADIN(VaadinServlet.java:790)
com.vaadin.server.VaadinServlet.serveStaticResources(VaadinServlet.java:760)
com.vaadin.server.VaadinServlet.service(VaadinServlet.java:257)
com.vaadin.server.VaadinServlet.service(VaadinServlet.java:201)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
root cause
java.lang.ClassNotFoundException: com.vaadin.sass.internal.ScssStylesheet
org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:501)
org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:421)
org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:412)
org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
java.lang.ClassLoader.loadClass(ClassLoader.java:356)
com.vaadin.server.VaadinServlet.serveOnTheFlyCompiledScss(VaadinServlet.java:957)
com.vaadin.server.VaadinServlet.serveStaticResourcesInVAADIN(VaadinServlet.java:790)
com.vaadin.server.VaadinServlet.serveStaticResources(VaadinServlet.java:760)
com.vaadin.server.VaadinServlet.service(VaadinServlet.java:257)
com.vaadin.server.VaadinServlet.service(VaadinServlet.java:201)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)[/code]
com.vaadin.sass.internal.ScssStylesheet class is offered by vaadin-theme-compiler-7.x.x.jar but the server doesn't import this package. Then, I "hacked" the vaadin server bundle by adding DynamicImport-Package: * in vaadin server's MANIFEST. The previous exception does not appear but I got the same for org.w3c.css.sac.CSSException.
Note that by deploying the application .war file on tomcat, I had no error and the app looks like I expected (because all libraries are added under WEB-INF/lib and tomcat add them on the class loader). So, the problem is pure OSGi.
based on the Vaadin 7.1.3 bundles, the following changes need to be made:
import com.vaadin.theme-compiler in com.vaadin.server
import org.w3c.css.sac in com.vaadin.shared.deps and com.vaadin.theme-compiler
provide a ScssStylesheetResolver via ScssStylesheet.setStylesheetResolvers which loads from bundle resources, not (only) filesystem / classloader as the default implementation.
if you import parts of the original themes in your theme, consider creating it as a fragment to com.vaadin.themes, which in turn can then be used as a base for the ScssStylesheetResolver
This sounds like a packaging bug in Vaadin which should be reported to the authors. If the core Vaadin bundle needs to access classes from the package com.vaadin.sass.internal then it should include that in its Import-Package header.
With respect to org.w3c.css.sac, you don't specify which bundle throws an error but it sounds like the same kind of problem. Whichever bundle uses that package should import it via Import-Package.

Categories

Resources