在un-invoked函数中的Clojure(让[frame(java.awt.Frame。)])导致AWT被启动

时间:2014-02-15 20:45:44

标签: clojure awt leiningen

在阅读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)并没有表现出相同的症状。

1 个答案:

答案 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来查看。