本文已經(jīng)發(fā)布于InfoQ中文站(http://www.infoq.com/cn/news/2007/07/java-securejsh-publish),感謝Complystill為我們貢獻(xiàn)了SJSH這個(gè)項(xiàng)目。
JavaEye上活躍的開(kāi)發(fā)者Complystill(歆淵)最近發(fā)布了自己的開(kāi)源SecureJSH項(xiàng)目,提供了一個(gè)通過(guò)SSH交互進(jìn)行Java應(yīng)用開(kāi)發(fā)或者管理的工具。
在項(xiàng)目的介紹中可以得知,SecureJSH與Ptyhon里面的ipython或者Ruby里面的irb非常相似。它們都允許交互式運(yùn)行語(yǔ)言的代
碼,以方便跟蹤或者調(diào)試應(yīng)用。但是,Java與Ruby、Python不同,后者是動(dòng)態(tài)腳本語(yǔ)言,它們天生具有解釋執(zhí)行的特點(diǎn)(注意:當(dāng)然Python支
持預(yù)編譯,Ruby也將在YARV中開(kāi)始支持,這里指它們的解釋執(zhí)行狀態(tài))。我們常見(jiàn)的Python和Ruby發(fā)行版本基本上都包括自己的解釋器(這也是
它們的核心組件),但是Java是一種需要中間編譯過(guò)程的語(yǔ)言,默認(rèn)情況下它無(wú)法直接解釋運(yùn)行,也沒(méi)有相應(yīng)的解釋器。
那么SecureJSH是如何實(shí)現(xiàn)的呢?讀者首先會(huì)想到JSR-223,這個(gè)API可以自己擴(kuò)展腳本語(yǔ)言支持,比如rhino是
Javascript解釋引擎。但是使用它難以實(shí)現(xiàn)交互操作,因?yàn)樗仨気斎胍粋€(gè)相對(duì)完整的腳本才可以運(yùn)行,這樣會(huì)喪失一部分交互性。SecureJSH
實(shí)際上是使用了JDK 6.0的新特性Java Compiler
API(JSR-199),它提供了一組API來(lái)讓程序可以動(dòng)態(tài)地訪問(wèn)Java編譯器的接口,這樣就可以使用Java編譯器動(dòng)態(tài)檢查代碼語(yǔ)法或者動(dòng)態(tài)根據(jù)
Java源碼生成可以執(zhí)行的字節(jié)碼。這種方式與ASM的編程直接生成字節(jié)碼不同,它能直接將Java源碼轉(zhuǎn)換為字節(jié)碼,XRuby的主力開(kāi)發(fā)者鄭曄(網(wǎng)名
dreamhead)在他的Blog中這樣對(duì)比了兩種方案:
之前,剛剛在Blog中提到ASM,
里面的代碼生成工作是通過(guò)直接寫(xiě) 字節(jié)碼完成的?,F(xiàn)在有了Compiler
API,可以考慮生成代碼以Java源碼的形式完成,然后,通過(guò)調(diào)用Compiler
API對(duì)源碼進(jìn)行動(dòng)態(tài)編譯,這樣,可以達(dá)到同直接寫(xiě)字節(jié)碼類(lèi)似的作用。使用Compiler
API,肯定不如直接生成字節(jié)碼來(lái)得高效,但對(duì)于不了解JVM指令的人來(lái)說(shuō)這也許是一種解決方案。
可見(jiàn)JSR-199不是最高效的字節(jié)碼生成方案,但是更方便使用。Java Compiler
API不是為了取代ASM這樣的方案的,它的本意是以編程的方式實(shí)現(xiàn)實(shí)時(shí)編譯及信息反饋。Java目前的主要架構(gòu)師之一Peter von der
Ahé曾經(jīng)在他的Blog對(duì)誰(shuí)需要使用Java Compiler API這個(gè)問(wèn)題做了如下解釋:
99%的Java開(kāi)發(fā)者都不需要了解Java Compiler
API。只有少數(shù)的開(kāi)發(fā)者會(huì)直接應(yīng)用這個(gè)API。但是IDE、Java
EE應(yīng)用程序服務(wù)器、Maven或者Ant還有測(cè)試框架的開(kāi)發(fā)者卻不一樣,他們有一個(gè)共同點(diǎn),就死需要調(diào)用編譯器將Java源碼轉(zhuǎn)換為類(lèi)文件(他們是這個(gè)
API的潛在用戶(hù))。
可見(jiàn)JSR-199的產(chǎn)生主要是面向熱部署或者增量編譯這樣的場(chǎng)合,但是SecureJSH的產(chǎn)生擴(kuò)展了Java Compiler API的應(yīng)用場(chǎng)景,同時(shí)也增強(qiáng)了Java和JVM的交互性。Complystill這樣介紹了SecureJSH的應(yīng)用場(chǎng)景和需求:
SecureJSH允許Java編寫(xiě)的服務(wù)器端應(yīng)用程序?yàn)楣芾韱T、客戶(hù)、開(kāi)發(fā)者和客戶(hù)端服務(wù)提供一個(gè)安全shell,這里可以交互性地讓Java語(yǔ)言逐句運(yùn)行。SecureJSH需要JDK 6.0或者JRE 6.0加JAVAC(在classpath中)來(lái)運(yùn)行。
SecureJSH的官方首頁(yè)這樣描述了它的主要特性:
- 安全:SecureJSH在服務(wù)器端實(shí)現(xiàn)了RFC-4251,SSH 2.0協(xié)議,支持公鑰認(rèn)證,這種方式方便安全(不需要每次輸入密碼)。
- 交互式執(zhí)行:傳
統(tǒng)的方式下,在運(yùn)行Java源代碼之前你必須將它們編譯為字節(jié)碼。但是使用SecureJSH,編譯的過(guò)程是透明完成的,所以你只需要隨意輸入一些
Java表達(dá)式(就可以運(yùn)行)。這意味著你可以使用你書(shū)寫(xiě)應(yīng)用程序時(shí)完全相同的語(yǔ)法,與最新的Java語(yǔ)言規(guī)范同步。你可以在你的Java項(xiàng)目源碼和
SecureJSH終端里面拷貝&粘貼任何代碼,都沒(méi)有問(wèn)題。
- 智能命令識(shí)別,UNIX Shell風(fēng)格:不
像JSR-223(Java Scripting
Engin,Java腳本引擎)對(duì)Java語(yǔ)言的腳本的支持,在(Java腳本引擎)里面你必須將Java類(lèi)的全部代碼輸入后才可以執(zhí)行,
secureJSH更加智能和人性化,如果你輸入了不完整的Java表達(dá)式,它會(huì)自動(dòng)提示你進(jìn)行多行的輸入,然后將這些表達(dá)式包裝到一個(gè)預(yù)先定義的類(lèi)結(jié)構(gòu)
中來(lái)執(zhí)行。它是一個(gè)真正的Shell。
- 沒(méi)有相互干擾,最小化資源消耗:SecureJSH沒(méi)有需要儲(chǔ)存在JVM范圍的靜態(tài)資源,每一個(gè)實(shí)例只消耗很少量的資源(基于NIO實(shí)現(xiàn),所有的SSH通訊都由一個(gè)線程處理)。你可以按照你的想法在一個(gè)JVM里面運(yùn)行任意多個(gè)shell服務(wù),包括Java應(yīng)用程序服務(wù)器的JVM。
作為一個(gè)開(kāi)源項(xiàng)目,SecureJSH使用了ganymed的純Java實(shí)現(xiàn)的SSH 2.0庫(kù),并使用Java
NIO編寫(xiě)了網(wǎng)絡(luò)服務(wù),代碼質(zhì)量很高。據(jù)Comply
Still介紹,SecureJSH最初是為內(nèi)存數(shù)據(jù)庫(kù)TOB設(shè)計(jì)的,為這個(gè)面向?qū)ο髷?shù)據(jù)庫(kù)提供交互訪問(wèn)的接口,但是后來(lái)作者發(fā)現(xiàn)它可以被應(yīng)用在很多場(chǎng)
合,所以單獨(dú)開(kāi)源發(fā)布。作為Java開(kāi)發(fā)者,您可以從這里下載源碼從中學(xué)習(xí)SSH 2.0、NIO網(wǎng)絡(luò)服務(wù)、Java Compiler API的使用方法,相信一定會(huì)有所收獲。