3

So, I have a .class file, along with its absolute path, and I need to know how you would go about executing that .class file from inside Java. It would be great if I were able to get a Class object from it, too.

I'm aware of the loadClass method in ClassLoader, but it requires the file's "binary name." I'm not sure if it's possible to get an external .class file's binary name, but if you can, that would work greatly! If not, however, is there any other way to execute or get an instance of an external .class file?

/*For those of us who work better with examples..
Let's say I have a .class file located at C:/Users/USER/Desktop. So..*/

String absolutePath = "C:/Users/USER/Desktop/FILE.class";

/*Now, having that, how would I get an instance of that class, or,
at least, execute it?*/
Lii
  • 11,553
  • 8
  • 64
  • 88
Steven
  • 1,709
  • 3
  • 17
  • 27
  • What do you mean by "execute" it? Does it have a `main` method you wish to invoke? You may wish to refer to http://stackoverflow.com/questions/738393/how-to-use-urlclassloader-to-load-a-class-file – Thorn G Dec 05 '12 at 00:57
  • 1
    1) Is `FILE.class` in the default package, the `Desktop` package or something else? 2) Reflection is the way to achieve what you want (barring point 4). It generally requires having the class on the class-path (Typically via an `URLClassLoader`) then loading it by the fully qualified name e.g. `our.com.File`. 3) Reflection is sometimes vital, but most often the wrong solution to the right user feature. What is the user feature this will offer? 4) A class with `static public void main(String[])` might be invoked in a separate `Process` using a `ProcessBuilder`. – Andrew Thompson Dec 05 '12 at 00:57

1 Answers1

5

The trick is going to be accessing ClassLoader's defineClass methods. Let's say you wanted to dynamically load a random class file that implemented a known interface (If you don't know the interface you would use reflection api to find and call methods).

package com.example.fileclassloader;

public interface Dynamo {
    public Integer beDynamic(String s);
}

Somewhere is a compiled class that implements that interface. It may look something like:

public class Sample implements com.example.fileclassloader.Dynamo {

  public Integer beDynamic(String s) {
    System.out.println(String.format("The value is: %s", s));
    return s.length();
  }
}

Now to use it we need to extend a class loader so we can access the defineClass method. This one will just take in the filename, load the bytes and create the instance:

package com.example.fileclassloader;

import java.io.File;
import java.io.IOException;
import java.security.SecureClassLoader;

public class MyDynamoClassLoader extends SecureClassLoader {

       public Object createObjectFromFile(String fileName) throws 
                InstantiationException, IOException, IllegalAccessException {

            File file = new File(fileName);
            byte[] classBytes =     
            org.apache.commons.io.FileUtils.readFileToByteArray(file);
            Class<?> clazz = defineClass(null, classBytes, 0, classBytes.length);
            return clazz.newInstance();
        }
}

Now we need to use the dynamically loaded class instance. We cast it to the interface we are expecting it to conform to, and use it like any other instance of the interface:

package com.example.fileclassloader;

import java.io.FileNotFoundException;
import java.io.IOException;

public class App {

    public static void main() throws FileNotFoundException, IOException, 
                           InstantiationException, IllegalAccessException {

        String fname = "target/classes/com/example/fileclassloader/Sample.class";

        MyDynamoClassLoader loader = new MyDynamoClassLoader();
        Dynamo dynamo = (Dynamo) loader.createObjectFromFile(fname);
        Integer i = dynamo.beDynamic("Testing");

        System.out.println(String.format("Dynamo (%s) returned %d", fname, i));

    }

}

And for good measure, here is the pom.xml file for building it:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>fileclassloader</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
    </dependencies>
</project>
Jeff Putney
  • 403
  • 3
  • 8