1

I was testing an example of accessing private method from another class and got an exception

public class WithoutMain 
{       
    public static void main(String args[]) throws Exception
    {
        Class c = Class.forName("A");
        Object o = c.newInstance();
        Method m = c.getDeclaredMethod("message", null);
        m.setAccessible(true);
        m.invoke(o, null);
    }
}

public class A {

    private void message(){ 
        System.out.println("This is a private method.");
    }
}

Getting following exception

Exception in thread "main" java.lang.ClassNotFoundException: A
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)

These 2 class resides in same package. Can anyone tell me why this exception shows?

3
  • 2
    what package A is in ? Commented Aug 31, 2013 at 18:51
  • Both class resides in same package. Commented Aug 31, 2013 at 18:53
  • @skabir What's the package name? Commented Aug 31, 2013 at 18:54

6 Answers 6

4

You need to use the fully qualified name of a class to load it using Class.forName()

Now you may argue why? As in your case both the classes are in the same directory/package.

I would argue the other way, there is no rule defined in java that the class loader will look in the same directory first.

If you want to learn how class loading works, I would suggest you source code for the class java.lang.ClassLoader class

So when you invoke the Class.forName it uses delegation and the class loader which is assigned the job to load this class will not know the current package or any location. Hence, it needs the fully qualified class name.

One more tip, in java a fully qualified class name of a loaded class is <ClassLoader><packageName><className>. This is how the classes in JVM are uniquely identified.

Hope this helps

EDIT

Your code will work only in one condition and that is, if both the classes are in default package.

Sign up to request clarification or add additional context in comments.

Comments

2

You have to provide the fully qualified name of the class, not only the simple class name.

Class c = Class.forName("<package>.A");

Comments

1

Try changing

    Class c = Class.forName("A");

to

    Class c = Class.forName("yourPackagePath.A");

the forName method does not take in account the package of the user call.

Comments

1

You need the FQN as per the docs:

Parameters:
   className - the fully qualified name of the desired class.

Comments

0

The Java Class class isn't in your package, so it needs to know where the class is located otherwise it doesn't know where it is in order to load it(just like the classloader loads it from a full file path).

so

Class<? extends Object> c = Class.forName("A");

needs to be

Class<? extends Object> c = Class.forName("package.A");

where package is the full qualified name of the package so if the package is

foo.bar

it would become

Class<? extends Object> c = Class.forName("foo.bar.A");

Comments

0

As already stated in answers before, needs full name.

To avoid manually typing it you can simply use:

Class<?> clazz = Class.forName(A.class.getName());

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.