clojure hacking guide -凯发k8网页登录

生活、程序、未来
   :: 凯发k8网页登录首页 ::  ::  :: 聚合  :: 管理

clojure hacking guide

posted on 2010-07-11 12:07 dennis 阅读(3543) 评论(1)     所属分类: 动态语言javaclojure
    这题目起的哗众取宠,其实只是想介绍下怎么查看clojure动态生成的字节码,这对分析clojure的内部实现很重要。

    第一步,下载最新的并解压,并导入到你喜欢的ide。

    其次,下载并解压。

    第三,删除clojure 1.1.0源码中的clojure.asm包。clojure并不是引用asm的jar包,而是将asm的源码合并到clojure中,并且删除一些只会在调试阶段用到的package和class,保留使用asm的最小源码集合,这可能是处于防止asm不同版本的jar包冲突以及缩小clojure大小的考虑。

    第四,将asm 3.0源码拷入clojure的源码中,并将包org.objectweb.asm包括子包整体重名名为clojure.asm。

    第五步,修改clojure源码,加入traceclassvisitor的适配器,用于跟踪字节码生成,这需要修改clojure.lang.compiler类中的两个compile方法,找到类似
classwriter cw = new classwriter(classwriter.compute_maxs);
// classwriter cw = new classwriter(0);
classvisitor cv = cw;

这样的代码,将cv修改为traceclassvisitor:
 classvisitor cv = new traceclassvisitor(new checkclassadapter(cw), new printwriter(system.out));

    traceclassvisitor的第二个参数指定将跟踪到的字节码输出到哪里,这里简单地输出到标准输出方便查看。

    第六步,接下来可以尝试下我们修改过的clojure怎么动态生成字节码,启动repl,
java clojure.main

启动阶段就会输出一些字节码信息,主要预先加载的一些标准库函数,如clojure.core中的函数等,repl启动完毕,随便输入一个表达式都将看到生成的字节码
user=> ( 1 2)

输出类似

compile 1
// class version 49.0 (49)
// access flags 33
public class user$eval__4346 extends clojure/lang/afunction  {

  
// compiled from: no_source_file
  
// debug info: smap
eval__4346.java
clojure
*s clojure
*f
 1 no_source_file
no_source_path
*l
0#1,1:0
*e

  
// access flags 25
  public final static lclojure/lang/var; const__0

  
// access flags 25
  public final static ljava/lang/object; const__1

  
// access flags 25
  public final static ljava/lang/object; const__2

  
// access flags 9
  public static <clinit>()v
   l0
    linenumber 
2 l0
    ldc 
"clojure.core"
    ldc 
""
    invokestatic clojure
/lang/rt.var (ljava/lang/string;ljava/lang/string;)lclojure/lang/var;
    checkcast clojure
/lang/var
    putstatic user$eval__4346.const__0 : lclojure
/lang/var;
    iconst_1
    invokestatic java
/lang/integer.valueof (i)ljava/lang/integer;
    putstatic user$eval__4346.const__1 : ljava
/lang/object;
    iconst_2
    invokestatic java
/lang/integer.valueof (i)ljava/lang/integer;
    putstatic user$eval__4346.const__2 : ljava
/lang/object;
    return
    maxstack 
= 0
    maxlocals 
= 0

  
// access flags 1
  public <init>()v
   l0
    linenumber 
2 l0
   l1
    aload 
0
    invokespecial clojure
/lang/afunction.<init> ()v
   l2
    return
    maxstack 
= 0
    maxlocals 
= 0

  
// access flags 1
  public invoke()ljava/lang/object; throws java/lang/exception 
   l0
    linenumber 
2 l0
   l1
    linenumber 
2 l1
    getstatic user$eval__4346.const__1 : ljava/lang/object;
    getstatic user$eval__4346.const__2 : ljava
/lang/object;
    invokestatic clojure
/lang/numbers.add (ljava/lang/object;ljava/lang/object;)ljava/lang/number;

   l2
    localvariable 
this ljava/lang/object; l0 l2 0
    areturn
    maxstack 
= 0
    maxlocals 
= 0
}
3

3就是表达式的结果。可以看到,一个表达式生成了一个class。其中是静态初始化块,主要是初始化表达式中的字面常量;不用说,默认的构造函数;invoke是核心方法,表达式生成的class,new一个实例后调用的就是invoke方法,执行实际的代码,高亮部分加载了两个常量,并执行number.add方法。

最后,请happy hacking!。




评论

# re: clojure hacking guide  回复     

2010-07-12 11:46 by
dasdsadas dnf免费外挂 一点贷 /forum.do/list/qryfirsort_7.html dasdasdasda

只有注册用户后才能发表评论。


网站导航:
              
相关文章:
 
网站地图