<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <body> <a href="user_guide.html">[index]</a><br> <a href="user_guide.html">[prev]</a> <a href="framework.html">[next]</a> <h1>1. Jiapi Reflection</h1> Jiapi reflection API is a foundation where rest of the Jiapi is built on. It provides a Java reflection like API to modify Java classes. The differences between Java reflection and Jiapi reflection are: <ul> <li><b>Jiapi reflection is a read/write API</b></li> Java reflection can only be used to query information from classes. Jiapi reflection can in addition modify the class itself. <li><b>Jiapi reflection is used for classes that are not yet loaded into a virtual machine</b></li> Java reflection is used to query classes which are already loaded into Java virtual machine. Jiapi reflection is used to form an in-memory object representation of a class. That is, an object graph which represents a class. The object representation can then be manipulated and loaded into a virtual machine later. </ul> <p> The prerequisite to understand Jiapi reflection, is to be comfortable with Java reflection. Some knowledge about Java bytecode is also needed. Feel free to skip this section if you are more interested to utilize Jiapi in a higher level of abstraction. <h2>1.1 Basic Concepts</h2> Java reflection API provides an abstraction for a <code>Class</code>, <code>Method</code> and <code>Field</code>. These abstractions can be used to query reflective information about classes and interfaces. Jiapi reflection extends this concept so that it is possible to alter the classes and interfaces too. <p> <img src="uml/jiapi_reflection.gif"> <p> Using <code>JiapiClass</code> it is possible to query and modify the class it represents. All bytecode modifications are done through <code>InstructionList</code> which represents the bytecode <code>Instructions</code> of a class. <h2>1.2 Examples</h2> <h3>Hello world 1</h3> This example adds a hello world functionality to a target class. The target class will be <code>Test.java:</code> <pre> package samples.reflect.hello1; import java.lang.reflect.Method; public class Test { public static void main(String args[]) throws Exception { Class cl = Test.class; Method m = cl.getMethod("helloWorld", new Class[] {}); HelloWorld hw = (HelloWorld) cl.newInstance(); m.invoke(hw, new Object[] {}); } } </pre> Please notice how <code>Test</code> gets a reference to its method <i>helloWorld</i>. It also creates an instance of itself and casts it to <code>HelloWorld</code>. If you try to run this class you would naturally get <code>NoSuchMethodException</code> and <code>ClassCastException</code>. This example shows how you can add these missing features to the class. <p> The <code>HelloWorld</code> interface looks like: <pre> package samples.reflect.hello1; public interface HelloWorld { public void helloWorld(); } </pre> The class modification is done in class <code>HelloWorldBuilder:</code> <pre> 1 package samples.reflect.hello1; 2 3 import java.io.FileOutputStream; 4 import java.lang.reflect.Modifier; 5 import alt.jiapi.reflect.*; 6 7 public class HelloWorldBuilder { 8 public HelloWorldBuilder() throws Exception { 9 // Load the target class: 10 Loader loader = new Loader(); 11 JiapiClass clazz = loader.loadClass("samples.reflect.hello1.Test"); 12 13 // Add an interface to a clazz: 14 clazz.addInterface("samples.reflect.hello1.HelloWorld"); 15 16 // Add an empty method for a clazz. The method signature must 17 // match the method from HelloWorld interface, the only difference 18 // is that we want to implement the method now so it can't be abstract. 19 JiapiMethod method = clazz.addMethod(Modifier.PUBLIC, "void", 20 "helloWorld", new String[] {}); 21 22 // Then create the method body. The body will make a call to 23 // System.out.println and then just return. 24 InstructionList il = method.getInstructionList(); 25 InstructionFactory iFactory = il.getInstructionFactory(); 26 il.add(iFactory.getField(loader.loadClass("java.lang.System").getField("out"))); 27 il.add(iFactory.constant("hello world!")); 28 il.add(iFactory.invoke(System.out.getClass().getMethod("println", new Class[] { String.class }))); 29 il.add(iFactory.returnMethod(method)); 30 31 // Finalize the modified class and dump it to the file: 32 clazz.doPreDefine(); 33 clazz.dump(new FileOutputStream("Test.class")); 34 } 35 36 public static void main(String args[]) throws Exception { 37 new HelloWorldBuilder(); 38 } 39 } </pre> To run this example set your CLASSPATH as specified in README file. Then say:<br> <code> java samples.reflect.hello1.HelloWorldBuilder </code> <p> You should now see a <code>Test.class</code> in your working directory. To verify if the <code>Test.class</code> works you can try to run it. First make a required package hierarchy and move <code>Test.class</code> there so that Java vitual machine finds it:<br> <code> mkdir -p samples/reflect/hello1 </code><br> <code> mv Test.class samples/reflect/hello1/ </code> <p> Then add . as a first element in your CLASSPATH and launch <code>Test</code>: <br> <code> export CLASSPATH=.:$CLASSPATH </code><br> <code> java samples.reflect.hello1.Test </code> <p> You should see a line "hello world!" in your console instead of <code>NoSuchMethodException</code> or <code>ClassCastException</code>. <p> <a href="user_guide.html">[prev]</a> <a href="framework.html">[next]</a> </body> </html>