views:

116

answers:

4

Is it possible to generate subclasses at runtime or while an application is running? If so, how is this achieved and what precautions should be taken to prevent a rogue object wreaking havoc inside an application?

Edit: Title modified from "Class generation on the fly".

+2  A: 

Take a look at Reflection API.

Create Dynamic class "on the fly"

Read this one too:

Java Reflection: Create an implementing class - Jon Skeet answered it! :)

Leniel Macaferi
+1  A: 

Yes. Have a look at what you can do with the compiler in Javassist.

Thorbjørn Ravn Andersen
+1  A: 

Yes, it is possible

Take a look at the package "javax.tools"

You could compile and load a class at runtime.

    String rogue = "package abc; "+
                 "public class RogueObjectWreakingHavoc extends SomeImportantClass {"+
                 " { System.exit(-1) }"+
                 "}"
    File sourceFile = new File("RogueObjectWreakingHavoc.java");
    FileWriter fileWriter = new FileWriter(sourceFile);
    fileWriter.write(rogue);
    fileWriter.close();

    List<File> files = new ArrayList<File>();
    files.add(sourceFile);

    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    StandardJavaFileManager fileManager = compiler.getStandardFileManager(null,
                                                                          null,
                                                                          null);

    compiler.getTask(null, 
                     fileManager,
                     null,
                     null,
                     null,
                     fileManager.getJavaFileObjectsFromFiles(files))
    .call();
    fileManager.close();

   // load using URLClassLoader...

To avoid it you most consider declare your classes as final if they are not indented to be subclasses, and make copies when needed ( instead of taking arguments just they way they are )

More information ( about how to use Java effectively ) on the book "Effective Java" by Joshua Bloch

OscarRyz
Lol at RogueObjectWreakingHavoc.java. It's alive! Thanks you for the example code.
James P.
Probably requires a JDK and not a JRE.
Thorbjørn Ravn Andersen
@Thorbjørn `ToolProvider.getSystemJavaCompiler()` will return `null` with a JRE (so you won't indeed be able to compile without a JDK).
Pascal Thivent
A: 

For other developpers seeking to add the possibility of extending their software, another approach for plugin behaviour is the forName() method of Class (used for example by JDBC) and Dynamic Class Loading.

http://mindprod.com/jgloss/classforname.html

James P.