Is it possible to somehow 'import' a new Java class into a running program and make use of it?
Could I have a program create a new File of type '.java' and then include it in the project files and reference it without having to restart the program?
The following is an example of what I mean:
import java.io.*;
public class Program {
File JClass = new File("JClass.java");
public static BufferedWriter out = null;
public static void main(String[] args) {
try {
out = new BufferedWriter(new FileWriter("JClass.java"));
out.write("public abstract class JClass {");
out.newLine();
out.newLine();
out.write(" public void printSomething(String a) {");
out.newLine();
out.write(" System.out.println(a);");
out.newLine();
out.write(" }");
out.newLine();
out.write("}");
out.close();
} catch (IOException e)
{
System.exit(-1);
}
//Somehow import JClass.java as a class here
JClass.printSomething("Yay! It worked!");
}
}
Resulting 'JClass.java' file:
public abstract class JClass {
public void printSomething(String a) {
System.out.println(a);
}
}
Similarly, would it be possible to create a copy of one of the project's source files, edit the code in the file, and then somehow force the changes upon the running program?
I do not care so much about practical application at this point. I am merely exploring different ideas I have had relating to programming. I also understand that this is potential for all sorts of disaster. Editing running code, and including classes on the fly (which I don't imagine would be checked for errors as the other classes are when the project is built), could have very unpredictable results. I merely want to play around with the idea.
That said, if anyone has any HELPFUL warnings or things to look out for, I would appreciate them. Otherwise, I would appreciate if people kept from responding 'This is a bad idea' or 'there are easier and better ways to solve problems'. I am NOT trying to solve a problem with this. I am only exploring the idea.
So, is this possible?
Javassist will let you modify existing classes and create new classes at run time. http://www.csg.is.titech.ac.jp/~chiba/javassist/
In the Javassist tutorial there is a section for defining a new class from scratch. Check out the API to see how to add new methods and so on. Check out CtNewMethod.make in the Javassist API.
Javassist is what is used by JBoss to implement aspect oriented programming.
You can also check out EATS (the instrument method will be of interest) which makes use of Javassist to add new code to existing methods at runtime. Eats isn't at a release version, but it works :o
JPDA provides some mechanisms for modifying classes that are already loaded by and running in the JVM.
You actually want a Compiler - look at java.lang.Compiler:
http://download.oracle.com/javase/6/docs/api/java/lang/Compiler.html
You can load a different class this way by compiling a new .class file.
This does not let you change a loaded class. To do that you also need a java.lang.instrument.ClassFileTransformer and that has to be specified on the command-line at runtime.
To answer some of your other questions:
Throwing one more out there: the Eclipse Java Compiler. Unlike BCEL, ASM, or Jasmin, you don't need to know assembly. ECJ is just a Java compiler written in Java.
You should look into on the fly class loading with ClassLoader
http://download.oracle.com/javase/1.5.0/docs/api/java/lang/ClassLoader.html
There are also mechanisms you can use to compile classes, but that's probably not going to be AS useful to you.