国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java也可以不用編譯直接執行了?

Benedict Evans / 2311人閱讀

摘要:那本文為什么說,可以不編譯直接執行了呢其實,這個是里新加的一個,目的是使單個文件的源碼可以無需編譯,直接執行。中還提到,在類操作系統下,上面的代碼還可以以形式執行。我們再寫一個例子看下看到沒,我們用寫的代碼居然可以像腳本一樣直接執行了。

我們都知道java是靜態語言,也就是說,如果你想執行java程序,就必須先編譯,再執行。

那本文為什么說,java可以不編譯直接執行了呢?

其實,這個是OpenJDK11里新加的一個feature,目的是使單個文件的java源碼可以無需編譯,直接執行。

下面的JEP里對該特性做了詳細的描述:

http://openjdk.java.net/jeps/330

我們先寫個小例子實驗下:

$ cat Test.java
public class Test {
  public static void main(String[] args) {
    System.out.println("hello");
  }
}
$ java Test.java
hello

真的可以執行,神奇。

JEP 330 中還提到,在類Unix操作系統下,上面的代碼還可以以 "Shebang" 形式執行。

我們再寫一個例子看下:

$ cat Test
#!/usr/bin/java --source 12
public class Test {
  public static void main(String[] args) {
    System.out.println("hello");
  }
}
$ chmod +x Test
$ ./Test
hello

看到沒,我們用java寫的代碼居然可以像shell腳本一樣直接執行了。

那這一切在JVM中又是怎么實現的呢?靜態語言為什么也可以像腳本一樣動態執行了呢?

下面我們來看下對應的JVM源碼:

// src/java.base/share/native/libjli/java.c
static jboolean
ParseArguments(int *pargc, char ***pargv,
               int *pmode, char **pwhat,
               int *pret, const char *jrepath)
{
    ...
    if (mode == LM_SOURCE) {
        ...
        *pwhat = SOURCE_LAUNCHER_MAIN_ENTRY;
        ...
    }
    ...
    *pmode = mode;
    return JNI_TRUE;
}

當我們要執行的java程序是java源文件時,該方法中的mode就會被設置為LM_SOURCE。

pwhat指針指向的是我們最終要執行的帶main方法的java類,由上我們可以看到,在mode為LM_SOURCE時,最終執行的java類并不是我們提供的java源文件對應的java類,而是SOURCE_LAUNCHER_MAIN_ENTRY宏定義的java類。

我們看下這個宏對應的java類是什么:

// src/java.base/share/native/libjli/java.c
#define SOURCE_LAUNCHER_MAIN_ENTRY "jdk.compiler/com.sun.tools.javac.launcher.Main"

由上可見,它是jdk.compiler模塊里的一個類,java命令最終執行的main方法就是這個類里的main方法。

那這個main方法的參數是什么呢?

其實就是我們提供的java源文件,不過為了更加明確,我們還是通過以下方式驗證下:

$ _JAVA_LAUNCHER_DEBUG=1 java Test.java
----_JAVA_LAUNCHER_DEBUG----
# 省略無關信息
Source is "jdk.compiler/com.sun.tools.javac.launcher.Main"
App"s argc is 1
    argv[ 0] = "Test.java"
# 省略無關信息
----_JAVA_LAUNCHER_DEBUG----
hello

如果我們在啟動java之前,設置了_JAVA_LAUNCHER_DEBUG環境變量,JVM內部就會輸出一些運行時的數據來供我們調試,比如,由上面的輸出我們可以看到,java命令將要執行的帶main方法的java類為jdk.compiler/com.sun.tools.javac.launcher.Main,其參數為Test.java,正好和我們上文中分析的是一樣的。

也就是說,當我們以源文件形式執行java命令時,最終調用的main方法是jdk.compiler/com.sun.tools.javac.launcher.Main里的main方法,其參數為我們要執行的java源文件。

下面我們再來看下這個main方法究竟是如何執行我們的源文件的:

// com.sun.tools.javac.launcher.Main
public class Main {
    ...
    public static void main(String... args) throws Throwable {
        try {
            new Main(System.err).run(VM.getRuntimeArguments(), args);
        } catch (Fault f) {
            ...
        }
    }
    ...
    public void run(String[] runtimeArgs, String[] args) throws Fault, InvocationTargetException {
        Path file = getFile(args); // 我們要執行的源文件
        ...
        String mainClassName = compile(file, getJavacOpts(runtimeArgs), context);

        String[] appArgs = Arrays.copyOfRange(args, 1, args.length);
        execute(mainClassName, appArgs, context);
    }
    ...
    private void execute(String mainClassName, String[] appArgs, Context context)
            throws Fault, InvocationTargetException {
        ...
        try {
            Class appClass = Class.forName(mainClassName, true, cl);
            Method main = appClass.getDeclaredMethod("main", String[].class);
            ...
            main.invoke(0, (Object) appArgs);
        } catch (ClassNotFoundException e) {
            ...
        }
    }
}

在這里我們只列出了相關方法的大致邏輯,不過已經足夠能看出,它到底是怎么執行的了。

我們要執行的源碼先被java的compiler編譯,然后又調用了其main方法繼續執行我們寫的邏輯。

原來是如此簡單。

不過,java源碼可動態執行的特性還是給我們留下了很多想像空間,雖然其實現機制很粗暴,但對用戶來說還算是友好的。

希望本篇文章能給各位同學帶來一些收獲。

完。

更多原創文章,請關注我微信公眾號:

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76052.html

相關文章

  • 【轉】Java的package和import機制

    摘要:比如說,就是復姓,名字為的類別則是復姓,名字為的類別。先介紹的機制基本原則需要將類文件切實安置到其所歸屬之所對應的相對路徑下。把源代碼文件,文件和其他文件有條理的進行一個組織,以供來使用。可以使用通配符,代表某下所有的,不包括子目錄。 一些人用了一陣子的Java,可是對于 Java 的 package 跟 import 還是不太了解。很多人以為原始碼 .java 文件中的 import...

    anRui 評論0 收藏0
  • Java虛擬機學習

    摘要:虛擬機學習是一個虛構出來的計算機有自己的處理器堆棧寄存器以及相應的指令系統等。類裝載器子系統涉及虛擬機的其它組成部分和來自庫的類。運行中的程序的每一個線程都是一個獨立的虛擬機執行引擎的實例。 Java虛擬機學習 JVM JVM是一個虛構出來的計算機,有自己的處理器,堆棧,寄存器以及相應的指令系統等。JVM是JRE的一部分,通過在實際的計算機上仿真模擬各種計算機功能,這樣就能使Java在...

    RobinTang 評論0 收藏0
  • 3. 第一個 Java 程序 - Hello World 【連載 3】

    摘要:需要注意的地方輸入法狀態調整為英文狀態代碼的縮進不要忘記分號下面圖片標注內容。語句語句是程序最小的一個執行單位,像一個指令,程序中,必須使用一個英文分號結束一條語句。建議,第一個簡單的程序,我已經詳細的為你做了演練與解釋。 在上一篇文章 【[準備編譯環境】]()中我們完成了 Java 編譯環境的搭建,這篇文章內容主要是來教你怎么開始編寫第一個 Java 程序,并運行它。 分為兩個步驟,...

    shevy 評論0 收藏0
  • 學習JVM是如何從入門到放棄的?

    摘要:而字節碼運行在之上,所以不用關心字節碼是在哪個操作系統編譯的,只要符合規范,那么,這個字節碼文件就是可運行的。好處防止內存中出現多份同樣的字節碼安全性角度特別說明類加載器在成功加載某個類之后,會把得到的類的實例緩存起來。 前言 只有光頭才能變強 JVM在準備面試的時候就有看了,一直沒時間寫筆記。現在到了一家公司實習,閑的時候就寫寫,刷刷JVM博客,刷刷電子書。 學習JVM的目的也很簡單...

    Joyven 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<