1

I have a school assignment where the instructor has provided two .class files to do some basic things like simulating reading and writing to a database and taking web input. Unfortunately, the classes were left in the default package which stops me from having a directory structure. I want to allow a directory structure, which requires packages so I am using reflection to load the class and call methods. Unfortunately, I am getting an error:

Exception in thread "main" java.lang.NoClassDefFoundError: Reservation
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2688)
    at java.lang.Class.getMethod0(Class.java:2937)
    at java.lang.Class.getMethod(Class.java:1771)
    at framework_proxy.FrameWorkController.initialize(FrameWorkController.java:54)
    at framework_proxy.Main.main(Main.java:12)

Here are the methods in question:

private static Class<?> frameWork;

private FrameWorkController() {
    //Class.forName("Framework").getMethod("someMethod").invoke(null);
    try {
        frameWork = Class.forName("Framework");
        aval = new Availabilities(frameWork.getField("NUM_SINGLE_ROOMS").getInt(null),
                Class.forName("Framework").getField("NUM_DOUBLE_ROOMS").getInt(null));
    } catch (IllegalArgumentException | IllegalAccessException
            | NoSuchFieldException | SecurityException
            | ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
// Initialize the framework to read instructions from the given file
public static void initialize(String fileName) throws IllegalAccessException, IllegalArgumentException, 
    InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException {

    System.out.println("Reading input file");
    Path currentRelativePath = Paths.get("");
    String s = currentRelativePath.toAbsolutePath().toString();
    System.out.println("Current Relative Path is: " + s);
    frameWork.getMethod("init").invoke(fileName);

    while ((boolean) Class.forName("Framework")
        .getMethod("hasNextInstruction").invoke(null)) {
        //get the instruction data for the next instruction from the framework
        String[] instructionData = (String[]) Class.forName("Framework").getMethod("nextInstruction").invoke(null);
        //the first line of every instruction contains the instruction number
        int instruction = Integer.parseInt(instructionData[0]);
        //pass off the handling of the instruction to a different function
        handleInstruction(instruction, instructionData); 
    }
}

I believe this has to be an issue with my runtime class path, however I have created a jar file from the class files I was provided and added that to the class path. Additionally, from the error message you can see this isn't causing an error until the call to get the method from the framework. As you can see the constructor call to the constants from the framework are working fine.

Any points in the correct direction are much appreciated.

Edit New Info

After running the code through the debugger, I can see that the declared public fields getting initialized to the ten fields in the framework, however, the declared public methods do not get initialized.

joshu
  • 463
  • 8
  • 18
  • That's interesting. `Reservation` seems to be a class that `Framework` references but it's not loaded when `Framework` is loaded... (You mentioned two classes, so `Framework` is one and `Reservation` is the other, no?) If you just want to poke it, you could try `Class.forName("Reservation");` and see if that works. I mean I think `forName` should also load classes which are referenced by the class you pass to it but it seems to not be doing that for you here. Hopefully somebody who is more familiar with the technicalities of this will see your question. – Radiodef Apr 09 '16 at 00:16
  • Reservation isn't a class that is part of the class file the professor included, it is oddly enough one that I wrote... Specifically a class that the framework uses. Could it be because the framework is already compiled? – joshu Apr 09 '16 at 00:21
  • Well, what's strange to me is that it is getting thrown by `getMethod`. I don't even know what the circumstances of that happening actually are. It's not documented... I did a little Googling and I found [this answer](http://stackoverflow.com/a/5756989/2891664) which says that this can happen if the class loading fails due to e.g. `ExceptionInInitializerError`. This means for example you have a `static {...}` block or static field initializer in `Reservation` that throws an exception. But I think the `ExceptionInInitializerError` should be thrown by`Class.forName` if that were the case. – Radiodef Apr 09 '16 at 00:39
  • Well perhaps one more thing I was missing. The framework which is in the default package and the Reservations class it uses were in different packages. So I'm sure that is causing an error. – joshu Apr 09 '16 at 00:47
  • That could be. Here's an Ideone example showing the `ExceptionInInitializerError` thing I described in my other comment: http://ideone.com/nSnxMn – Radiodef Apr 09 '16 at 00:47
  • 1
    Thats a really interesting example. Since I am new to this reflection stuff. As it turns out. The classes not being in the correct package was the problem. To fix it I moved the classes to the default package and made a jar of all the files I needed and added it to the class path. Thanks for your help! – joshu Apr 09 '16 at 01:08

0 Answers0