差分表示
- 最後の更新で追加された行はこのように表示します。
- 最後の更新で削除された行は
このように表示します。
*対象ソースファイル
ソースはこんな感じ。
--(
public class HelloAspectWorld {
public static void main(String [] args){
new HelloAspectWorld().sayhello();
}
void sayhello(){
System.out.println("Hello World");
}
}
--)
ajcで作ったクラスを[[jode>http://jode.sourceforge.net/]]で戻してみた。~
あとでバイトコードを出しているが、そっちから判断できる通りのソースになってる。
--(
public class HelloAspectWorld
{
public static void main(String[] args) {
HelloAspectWorld helloaspectworld = new HelloAspectWorld();
try {
Trace.aspectOf().ajc$before$Trace$1$705b637b();
helloaspectworld.sayhello();
} catch (Throwable throwable) {
''// ここの処理は確かにbytecode上、合ってそうだが、何でこうなってるのか意味不明''
Trace.aspectOf().ajc$after$Trace$2$705b637b();
throw throwable;
}
Trace.aspectOf().ajc$after$Trace$2$705b637b();
}
void sayhello() {
System.out.println("Hello World");
}
}
--)
で、Aspectのクラスはこんな感じ。
--(
aspect Trace {
pointcut atSayHello(): call(void HelloAspectWorld.sayhello());
before(): atSayHello() {
System.out.println("[Before sayhello()]");
}
after(): atSayHello() {
System.out.println("[After sayhello()]");
}
}
--)
こっちも[[jode>http://jode.sourceforge.net/]]で戻して?みた。~
''jodeの逆コンパイルコードで、生成ミスってる所は適当に修正済''~
こちらはテストコードを試した時は気にならなかったが、Aspectはクラスロードの時点で、Aspectのインスタンスを singletonで用意してるコードになっているようだ。
--(
import org.aspectj.lang.NoAspectBoundException;
public class Trace
{
private static Throwable ajc$initFailureCause;
public static Trace ajc$perSingletonInstance;
static {
try {
ajc$postClinit();
} catch (Throwable throwable) {
ajc$initFailureCause = throwable;
}
}
Trace() {
/* empty */
}
public void ajc$before$Trace$1$705b637b() {
System.out.println("[Before sayhello()]");
}
public void ajc$after$Trace$2$705b637b() {
System.out.println("[After sayhello()]");
}
public static Trace aspectOf() {
Trace trace = ajc$perSingletonInstance;
if (trace != null)
return trace;
throw new NoAspectBoundException("Trace", ajc$initFailureCause);
}
public static boolean hasAspect() {
if (ajc$perSingletonInstance != null)
return true;
return false;
}
private static void ajc$postClinit() {
ajc$perSingletonInstance = new Trace();
}
}
--)
*コンパイルと実行
コンパイルは相当微妙で、こんな感じ。
AspectJ コンパイラは 1.2版で[[配布>http://www.eclipse.org/aspectj/]]されている。~
コンパイル時にCLASSPATHに同梱の aspectjrt.jarが必須。
aspectjrt.jarが無いと、ajc自体が動かない。
--(
% ajc *.java
--)
ちなみに ajcもそうだが、配布パッケージ内のコマンドはshell scriptで実体は aspectjtools.jarに
あるクラスのpublic static void main()を実行するようになってる。ajcの場合はこれ。
--(
"$JAVA_HOME/bin/java" -classpath" $ASPECTJ_HOME/lib/aspectjtools.jar:$JAVA_HOME/lib/tools.jar:$CLASSPATH" -Xmx64M org.aspectj.tools.ajc.Main "$@"
--)
''注意:''何でそうしてるのか分からないが、Aspectのファイルのsuffixは.javaで無いとajcのコンパイル対象にならないようだ。
* バイトコードを見てみる
%%予想される動作からすると、バイトコードに無理矢理 Aspect 呼び出しを差し込んでるだろう%%って事で、サクサクバイトコードを見てみる。~
どうも違うっぽい気がしてきたので、後で調査。~
ちなみにバイトコードは javap -c じゃなく、[[D-Java>http://cat.nyu.edu/~meyer/jvm/djava/]]の出力。~
まずはajcで作成した物。
--(
Major version: 46
Minor version: 0
public synchronized class HelloAspectWorld extends Object
{
Method public void <init>()
>> max_stack=1, max_locals=1 <<
0 aload_0
1 invokenonvirtual #9 <Method Object.<init>():void>
4 return
Local variable table:
start length slot
0 5 0 this:HelloAspectWorld
Line number table:
pc line
0 6
Method public static void main(String[])
>> max_stack=2, max_locals=2 <<
0 new #2 <Class HelloAspectWorld>
3 dup
4 invokenonvirtual #16 <Method HelloAspectWorld.<init>():void>
7 invokestatic #43 <Method Trace.aspectOf():Trace>
10 invokevirtual #46 <Method Trace.ajc$before$Trace$1$705b637b():void>
13 invokevirtual #19 <Method HelloAspectWorld.sayhello():void>
16 goto 28
19 astore_1
20 invokestatic #43 <Method Trace.aspectOf():Trace>
23 invokevirtual #49 <Method Trace.ajc$after$Trace$2$705b637b():void>
26 aload_1
27 athrow
28 nop
29 invokestatic #43 <Method Trace.aspectOf():Trace>
32 invokevirtual #49 <Method Trace.ajc$after$Trace$2$705b637b():void>
35 nop
36 return
Exception table:
from to target type
7 16 19 <Class Throwable>
Local variable table:
start length slot
0 37 0 args:String[]
Line number table:
pc line
0 9
36 10
Method void sayhello()
>> max_stack=2, max_locals=1 <<
0 getstatic #27 <Field System.out:PrintStream>
3 ldc #29 <String "Hello World">
5 invokevirtual #35 <Method PrintStream.println(String):void>
8 return
Local variable table:
start length slot
0 9 0 this:HelloAspectWorld
Line number table:
pc line
0 13
8 14
}
--)
んで次は javacで作成した物
--(
Major version: 46
Minor version: 0
public synchronized class HelloAspectWorld extends Object
{
Method public void <init>()
>> max_stack=1, max_locals=1 <<
0 aload_0
1 invokenonvirtual #1 <Method Object.<init>():void>
4 return
Line number table:
pc line
0 6
Method public static void main(String[])
>> max_stack=2, max_locals=1 <<
0 new #2 <Class HelloAspectWorld>
3 dup
4 invokenonvirtual #3 <Method HelloAspectWorld.<init>():void>
7 invokevirtual #4 <Method HelloAspectWorld.sayhello():void>
10 return
Line number table:
pc line
0 9
10 10
Method void sayhello()
>> max_stack=2, max_locals=1 <<
0 getstatic #5 <Field System.out:PrintStream>
3 ldc #6 <String "Hello World">
5 invokevirtual #7 <Method PrintStream.println(String):void>
8 return
Line number table:
pc line
0 13
8 14
}
--)
Last-modified: 2006-01-13 17:39:31