在阅读Clojure的Joy书时,我已经成功地定义了一个函数,当调用它时,它将在java.awt.Frame上创建和绘制。
(defn draw-frame [f x y]
(let [frame (java.awt.Frame.)]))
然而,在新的Leiningen空项目中简单地定义新Leiningen REPL中的功能会导致AWT框架启动。我这样说,因为输入上面的函数定义会导致一个新的OS X'窗口'打开'main'菜单选项。如果我关闭此窗口,则clojure REPL退出。
否则,该函数继续按预期运行,但我很想知道为什么会发生这种情况 - 在Java中创建类似的函数(引用但不实例化java.awt.Frame)并没有表现出相同的症状。
答案 0 :(得分:0)
通过rt.jar
进行一些探索,我能够稍微跟踪它。
java.awt.Frame的静态初始化程序[1]如下所示:
0: iconst_0
1: putstatic #20 // Field nameCounter:I
4: invokestatic #114 // Method java/awt/Toolkit.loadLibraries:()V
7: invokestatic #115 // Method java/awt/GraphicsEnvironment.isHeadless:()Z
10: ifne 16
13: invokestatic #116 // Method initIDs:()V
16: new #117 // class java/awt/Frame$1
19: dup
20: invokespecial #118 // Method java/awt/Frame$1."<init>":()V
23: invokestatic #119 // Method sun/awt/AWTAccessor.setFrameAccessor:(Lsun/awt/AWTAccessor$FrameAccessor;)V
26: return
我能够通过在REPL上执行java.awt.Toolkit
来重现行为,所以我也挖掘了静态初始化器:
0: ldc_w #150 // class java/awt/Toolkit
3: invokevirtual #151 // Method java/lang/Class.desiredAssertionStatus:()Z
6: ifne 13
9: iconst_1
10: goto 14
13: iconst_0
14: putstatic #126 // Field $assertionsDisabled:Z
17: iconst_0
18: putstatic #84 // Field loaded:Z
21: new #152 // class java/awt/Toolkit$3
24: dup
25: invokespecial #153 // Method java/awt/Toolkit$3."<init>":()V
28: invokestatic #32 // Method java/security/AccessController.doPrivileged:(Ljava/security/PrivilegedAction;)Ljava/lang/Object;
31: pop
32: invokestatic #154 // Method loadLibraries:()V
35: invokestatic #155 // Method initAssistiveTechnologies:()V
38: invokestatic #156 // Method java/awt/GraphicsEnvironment.isHeadless:()Z
41: ifne 47
44: invokestatic #157 // Method initIDs:()V
47: return
loadLibraries
似乎很有趣,因此反汇编看起来像:
0: getstatic #84 // Field loaded:Z
3: ifne 23
6: new #85 // class sun/security/action/LoadLibraryAction
9: dup
10: ldc #86 // String awt
12: invokespecial #87 // Method sun/security/action/LoadLibraryAction."<init>":(Ljava/lang/String;)V
15: invokestatic #32 // Method java/security/AccessController.doPrivileged:(Ljava/security/PrivilegedAction;)Ljava/lang/Object;
18: pop
19: iconst_1
20: putstatic #84 // Field loaded:Z
23: return
重写Clojure中的核心部分看起来像:
(doto (sun.security.action.LoadLibraryAction. "awt")
(java.security.AccessController/doPrivileged))
运行此命令会导致弹出相同的应用程序,因此我怀疑本机库是否具有导致它的初始化程序代码。不幸的是,我不想潜入真正的拆卸,所以其他人将不得不从这一点弄明白!
[1]:我解压缩了rt.jar,然后使用javap -p -c Foo.class
来查看。