0

I'm currently having problems with a little project I'm working on. In this project I'm trying to dynamically create Classes from a configuration String and load it into the JVM.

When I do this in a "normal" environment (Unit Tests) everything works fine. But when I try to create the Classes in an OSGI environment (Apache Karaf) I receive a ClassFormatError with the Message "Illegal class name "Ljava/lang/String;" in class ...".

After a short research I found out that this problem occurs for classes in java/lang when they are not loaded by the system class loader but I'm everything else than an expert when it comes to class loading in java and especially OSGi.

I think the way I'm getting access to the defineClass method could be of interest for this problem so here it is:

        PROTECTION_DOMAIN = (ProtectionDomain) AccessController.doPrivileged(new PrivilegedAction() {
        public Object run() {
            return RestEndpoint.class.getProtectionDomain();
        }
    });

    AccessController.doPrivileged(new PrivilegedAction() {
        public Object run() {
            try {
                Class loader = Class.forName("java.lang.ClassLoader");
                DEFINE_CLASS = loader.getDeclaredMethod("defineClass",
                        new Class[]{ String.class,
                                byte[].class,
                                Integer.TYPE,
                                Integer.TYPE,
                                ProtectionDomain.class });
                DEFINE_CLASS.setAccessible(true);
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            }
            return null;
        }
    });

The last (hopefully useful) piece of information is the ClassLoader I am invoking the defineClass method on when running my project in an OSGi bundle: It is an instance of org.apache.felix.framework.BundleWiringImpl.

It would be great if someone could help me out here!

Greetings, Pascal

EDIT: I need to define classes at runtime because I want to avoid boilerplate code in my project and make the program more consistent.

To be more precise my project will be a RESTful WebService. Since I'm using multiple technologies to store data and snychronize processes (mongoDB, MySQL, activeMQ, ...), I want to use Apache camel to deal with all the different technologies. The problem is that there is no possibility I know of to nicely integrate Camel with the Java approach on REST (The whole mapping of methods and classes to HTTP requests is done with Annotations). So the only possibility for me was to write methods which would place parameters of the request in the exchange headers of Camel and fire them to the route. To avoid this I wanted to automate this process by defining those classes at runtime from the route definitions.

Donald_W
  • 1,773
  • 21
  • 35
htipk
  • 109
  • 3
  • 10
  • Why are you trying to define the class `java.lang.String`? Surely that already exists and is defined by the boot classloader? In Java, only the boot classloader is permitted to define classes whose name begins with `java.`. – Neil Bartlett May 19 '14 at 06:37
  • Can you explain a bit why you do custom class creation? Perhaps there is even a nicer way to achieve what you want in OSGi. – Christian Schneider May 19 '14 at 07:42
  • @NeilBartlett I don't want to define java.lang.String. I want to define a completely new class which has e.g. an input parameter of type String. Christian, I updated the question so that you can make yourself a more precise picture of the problem. – htipk May 19 '14 at 14:50

1 Answers1

0

Write your own class loader whose parent is the bundle's class loader instead of trying to hack into the existing class loader.

BJ Hargrave
  • 9,324
  • 1
  • 19
  • 27
  • Finally got it to work. I don't think that hacking the existing classLoader was the problem because even after creating my custom classLoader I encountered the same problem, since there was a little error in the bytecode I created and the javax.ws.rs annotation classes were not on the bundle classpath (BND did not add them to the manifest). But with the custom classLoader approach it is way cleaner so thanks for that :). – htipk May 19 '14 at 22:42