Berne
Berne

Reputation: 627

Java Dynamic classloader throws ClassNotFoundException

I have a project that has it's own classloader. But I'm having a strange problem when loading some classes.

Basically, it is like:

@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
{
    // do some magic
    return myBrandNewClas;
}

But what happens is that, even returning a class, the Class.forName(...) still throws a ClassNotFoundException (example can be found here).

Another info: the returned class' name is different of the requested class name.

I'm start wondering whether it is a security lock of JVM (tested in Oracle JVM).

Thanks!

Upvotes: 2

Views: 317

Answers (2)

Berne
Berne

Reputation: 627

I could solve the problem by renaming the class to the desired class name.

import javassist.ClassPool;
import javassist.CtClass;


public class AAA
{
    public static class B
    {
        @Override
        public String toString()
        {
            return "B";
        }
    }

    private static class X extends ClassLoader
    {
        @Override
        protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
        {
            try
            {
                if ("A".equals(name))
                {
                    ClassPool cp = ClassPool.getDefault();
                    CtClass clazz = cp.get("AAA$B");

                    clazz.setName("A");
                    return clazz.toClass();
                }

                return super.loadClass(name, resolve);
            }
            catch (Exception e)
            {
                throw new RuntimeException(e);
            }
        }
    }

    public static void main(String[] args) throws Exception
    {
        X x = new X();
        System.out.println(Class.forName("A", true, x).newInstance().toString());
    }
}

This works well, so far. Now I'll put this code in my project.

Upvotes: 0

JP Moresmau
JP Moresmau

Reputation: 7403

The code for forName is native so it's harder to see, but yes I'd say the name is checked, because passing the correct name works:

public class BBB
{
public static class a {

}

private static class MyCL extends ClassLoader
{
    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
    {
        System.out.println("Hi, " + a.class.getName());
        return a.class;
    }
}

public static void main(String[] args) throws ClassNotFoundException
{
    MyCL cl = new MyCL();

    System.out.println(Class.forName("com.asg.util.BBB$a", true, cl));

}

Upvotes: 3

Related Questions