0

I've been trying to import a .class via absolute path while code is running and I don't know how to do it.

I found a way to import a class when it's already in project's build path by Class.forName();but I need to find a way to load a class that is not in build path.

The goal is:

  1. User is able to upload his own .class file which is then saved locally to a specific folder and path is saved in database
  2. Via GUI user can select this file to be used while code is running
  3. My code should load a class via this given absolute path while code is running

The problem is with 3rd point because I don't know if it is possible to load a class while code is running.

I've tried using URLClassLoader but I'm getting ClassNotFound error.

EDIT:

Basically, I have this static function which should return Class by it's name, but urlClassLoader.loadClass() throws error.

Name of a file is J48.class so for className argument I've tried using "J48", "J48.class" but none work.

Additionaly I've tried setting folder classifiers to build path and setting argument to "weka.classifiers.trees.J48" which is full path with package to this class (package structure is weka.classifiers.trees).

`public static Class getClassByName(String className) throws MalformedURLException, ClassNotFoundException 
    {
        URLClassLoader urlClassLoader = URLClassLoader.newInstance(new URL[] {
                   new URL("file:///D:\\xampp\\htdocs\\prog-ing\\classifiers\\")
        });

        Class class = urlClassLoader.loadClass(className);

        return class;
    }`
mr. Gauss
  • 601
  • 6
  • 14
  • 2
    “I've tried using URLClassLoader but I'm getting ClassNotFound error.” - post your code as a [mcve] so that people can help you. – Erwin Bolwidt May 29 '18 at 11:35
  • I added the function which is responsible for class loading. I've tried changing URL (/ and \\) and also changing class name from "J48" to "J48.class". – mr. Gauss May 29 '18 at 17:49
  • What is the package structure of the class you are trying to load? – Mad Physicist May 29 '18 at 17:52
  • I it's `classifiers.J48`, you need to shorten the URL by one path element and add the package name to the class instead. – Mad Physicist May 29 '18 at 17:52
  • Tried that, but it didn't work. Can I get around knowing package name? Because the goal is to let user upload any class which is then saved into a folder classifiers and I am loading class from that folder. This folder (D:/xampp/htdocs/prog-ing/classifiers) is not in build path, not sure if it should be, but I'm trying to avoid that. – mr. Gauss May 29 '18 at 18:29

2 Answers2

0

I think I have a suggestion to solve your problem...

I know two options:

  • Option 1: Read a class file from directory.

Example:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class Test5 extends ClassLoader {

    private static final String PATH = "C://myFiles//";

    public static void main(String[] args) {
        Class clazz = getClassFromName("Test4");
        System.out.println(clazz);
    }

    private static Class getClassFromName(String className) {
        File file = new File(PATH + className + ".class");

        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            byte[] bytes = new byte[fileInputStream.available()];

            fileInputStream.read(bytes);

            return defineClass(className, bytes, 0, bytes.length);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

}

This will print something like this:

class Test4


- Option 2: Read a class file from JAR.

Example:

import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

public class Test5 {

    private static final String PATH = "C://myFiles//";

    public static void main(String[] args) {
        Class clazz = getClassFromFile("myJar.jar", "com.mypackage.Test4");
        System.out.println(clazz);
    }

    private static Class getClassFromFile(String fromFile, String className) {
        try {
            URL url = new URL("file:////" + PATH + fromFile);
            URLClassLoader urlClassLoader = URLClassLoader.newInstance(
                new URL[] {
                    url
            });

            return urlClassLoader.loadClass(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }

        return null;
    }

}

This will print something like this:

class com.mypackage.Test4

Note that to read a jar file I had to put the full path of package to the class file.

I hope I've helped.

Denis Jr
  • 346
  • 2
  • 11
  • After I tried 1st solution I got an error: `Exception in thread "AWT-EventQueue-0" java.lang.ClassFormatError: Incompatible magic value 1212239428 in class file J48`. I tried changing .class to .java, same thing happened. I'm guessing file is not recognized as Java class for some reason, but I'm sure it should compile without error. – mr. Gauss May 30 '18 at 13:41
0

Okay so after thinking a bit, I only got to the one solution (still not satisfied with it) which is following:

every class that needs to be uploaded by user is saved into workspace of this project and therefore I am able to get class using Class.forName(); pointing out this "folder" of uploaded classes, in my case: Class.forName("classifiers.className");

mr. Gauss
  • 601
  • 6
  • 14