Loading class files, weird behavior.

edited June 2014 in How To...

Hi, I would like to load 'extensions' into my sketch dynamically. First by just loading .class files from my file system, later by loading them from a database. The problem is that I am not a java-wizard: I have looked up some snippets on how to use URLClassLoader to load a local .class file into my sketch, I just used a test .java file that I compiled and placed in my home folder. Loading goes without incidents as it seems, but when I try to access any of the methods (both static and non-static) or instantiate the class I get bathed in weird exceptions. Here is an abbreviated version of the code I am testing around with:

 //sketch_123.pde

import java.net.*;
import java.lang.reflect.*;

void setup(){
  File file = new File("/home/user/");

  try {
    URL url = file.toURL();
    URL[] urls = new URL[]{url};

    ClassLoader cl = new URLClassLoader(urls);
    Class cls = cl.loadClass("test");

    Object o = cls.newInstance();
    //InstantationException !!!

    Method m = cls.getDeclaredMethod("run");
    //NoSuchMethodException !!!

  } catch (MalformedURLException e) { print("Your URL was faulty.\n");
  } catch (ClassNotFoundException e) { print("The URL was not found.\n");
  }
}

And here is the test.java file that I simply compile with javac -g test.java -d /home/user

//test.java
//no package

public class test{
  public test(){}

  public static void run(){
  }

  public String get(){
  return "Hello World!"; 
  }
}

You can see the two exceptions I get while testing around with this commented in the sketch. I can get the methods of 'cls' by calling getDeclaredMethods(), I even made a loop that prints their names, but as soon as I try to invoke the method object I get an illegalaccessexception. Having found no possibly related answer to this on google I am starting to think it has something todo with processing and how it sets up the sketch and all that. Please help.

Answers

  • Never used getDeclaredMethod() before but getDeclaredField(). 1 tiny example below:

    /**
     * Enclosing Class Instance Reference (v1.02)
     * by GoToLoop (2014/May)
     *
     * stackoverflow.com/questions/763543/in-java-how-do-i-access-
     * the-outer-class-when-im-not-in-the-inner-class
     */
    
    void setup() {
      println(this);
      println(new Inner().q == this);
      exit();
    }
    
    class Inner {
      PApplet q;
    
      Inner() {
        try {
          q = (PApplet) getClass().getDeclaredField("this$0").get(this);
          println(q);
        }
    
        catch (ReflectiveOperationException cause) {
          throw new RuntimeException(cause);
        }
      }
    }
    

    Also there's this thread where I've messed a little more w/ that:
    http://forum.processing.org/two/discussion/5065/variable-names-using-another-variable

  • edited June 2014

    Instead of using the loaded class I have now simply added the .java file as a tab. I use .getClass() on an instance of test to recreate the situation I had before.

    ...
    test inst = new test();
    
    Class tclass = inst.getClass(); //tclass == cls (*in the first post)
    
    Constructor tconst = tclass.getConstructor(); //NoSuchMethodException !!!
    ...
    

    This seems especially weird. Even tho I know that I have declared a public no-args constructor for class test I can not get it.

  • edited June 2014

    Have you already attempted getDeclaredConstructor() instead of simply getConstructor()? #-o
    http://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getDeclaredConstructor-java.lang.Class...-

  • edited June 2014

    Have you already attempted getDeclaredConstructor() instead of simply getConstructor()?

    Yes. And because both versions don't work I am doing this:

        test f=new test();
    
        //f.getClass().getDeclaredConstructor();
    
        Constructor<test> a=null;
    
        for(Constructor<?> c:f.getClass().getDeclaredConstructors()){ 
          print(c.toString()+"\n"); 
          a=(Constructor<test>)c; 
          break; }
    
        test g=(test) a.newInstance(); //InstantiationException !!!
    
  • Okay, so I started up eclipse just now and tried the very same thing from above and guess what? In a separate java application everything works fine. Wow, lots of time wasted now. I guess I am just going to continue working on this in eclipse? :o

  • edited June 2014

    I've adapted the code I had about Field into Constructor and it worked:
    http://forum.processing.org/two/discussion/5065/variable-names-using-another-variable

    /**
     * Get Constructor Instantiation (v1.1)
     * by GoToLoop (2014/Jun)
     *
     * forum.processing.org/two/discussion/5678/
     * loading-class-files-weird-behavior-
     *
     * forum.processing.org/two/discussion/5065/
     * variable-names-using-another-variable
     */
    
    import java.lang.reflect.Constructor;
    
    void setup() {
      Constructor c = getClassConstructor(HashMap.class);
      HashMap h = (HashMap) getInstance(c);
      println(h);
    
      Constructor<PVector> pc = getClassConstructor(PVector.class);
      PVector p = getInstance(pc);
      println(p);
    
      Table t = getInstance(getClassConstructor(Table.class));
      println(t);
    
      exit();
    }
    
    static final <T> Constructor<T> getClassConstructor(Class<T> c) {
      try {
        return c.getDeclaredConstructor();
      }
    
      catch (NoSuchMethodException e) {
        println(e);
        return null;
      }
    }
    
    static final <T> T getInstance(Constructor<T> c) {
      try {
        return c.newInstance();
      }
    
      catch (InstantiationException e) {
        throw new RuntimeException(e);
      }
    
      catch (IllegalAccessException e) {
        throw new RuntimeException(e);
      }
    
      catch (java.lang.reflect.InvocationTargetException e) {
        throw new RuntimeException(e);
      }
    }
    
Sign In or Register to comment.