Sophie

Sophie

distrib > Mageia > 7 > armv7hl > media > core-release > by-pkgid > 0cfcb5752fd5bab453ee4654b78df045 > files > 13

jiapi-manual-0.4.0-8.mga7.noarch.rpm

<!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>