JAVA基礎-----------JVM內存分析之HelloWorld.java

JVM內存分析之HelloWorld.java


HelloWorld.java源碼如下:


public class HelloWorld {

    public static void main(String[] args) {

       String s ;

       s = "HelloHorld!";

       System.out.println("s = " + s);

    }

 

}

 


畫圖分析:

 



JVM執行分析:

首先自然是將源碼進行編譯啦!生成HelloWorld.class的字節碼文件。

輸入java  HelloWorld的命令運行java程序時,系統收到指令,就會創建java虛擬機線程,這個進程開始從classpath中找到HelloWorld.class文件,讀取這個文件中的二進制數據,然後把HelloWorld類的類信息存放到方法區的類代碼區中。這一過程稱爲類的加載過程

之後JVM主線程會去找main()這個主方法,開始執行方法裏面的指令。main()方法中形參args是字符串數組類型的,因爲String[]也是一個對象,所以在堆中開闢屬於它的內存空間。可以通過鍵盤輸入參數傳遞給args這個形參,保存在String[]的內存空間中。

第一條指令String  s;由於這個變量是在main()方法裏面,它是一個局部變量,所以jvm就爲它棧中開闢了一塊空間。

s = ”HelloWorld”中, ”HelloWorld”是常對象,在方法區的數據區的常量數據區開闢內存空間,開闢好空間後將這塊空間的地址付給了變量s,所以變量s存放的是地址,而不是”HelloWorld”這個字符串。

       System.out.println(“s= ” + s)中,因爲System是java標準類庫中的類,位於java,lang下,這個包是在java程序啓動時候,JVM的classLoder就會直接將它加載進來的,所以不需要人工手動導入就可以直接使用,這個System類在堆中開闢了三塊地址空間,分別屬於System.in,System.out,System.error。System.out.println()複寫了objecttoString()方法,得到返回來的s所指向地址的值,然後向控制檯輸出,最後換行。

輸出結果:s = Hello Horld!

 


附加1:類裝載器裝載字節碼的具體過程

     一個類裝載器本身也是一個java類,所以,類裝載器自身也需要被另外一個類裝載器裝載,這就出現了類似先有蛋,還是先有雞的問題。但JAVA中的類裝載器的這個問題卻很容易解決。JAVA的虛擬機(JVM)中內嵌了一個稱爲Bootstrap類裝載器,它是用特定於操作系統的本地代碼實現的,屬於JAVA虛擬機的內核,Bootstrap類不用專門的類裝載器去進行裝載。Bootstrap類負責加載JAVA核心包中的類(即rt.jar文件中的類),這些類的Class.getClassLoader()方法返回值爲null,即表示是Bootstrap類裝載器。JAVA核心包中有另外兩個類裝載器:ExtClassLoader和AppClassLoader,它們都是用JAVA語言編寫的JAVA類,其中ExtClassLoader類裝載負責加載存放在<JAVA_HOME>/jre/lib/ext目錄下的jar包中的類,AppClassLoader負責加載應用程序的啓動執行類,即當使用java命令去啓動執行一個類時,JAVA虛擬機使用AppClassLoader加載這個類。在編譯和運行JAVA程序時,都會通過ExtClassLoader類裝載器去<JAVA_HOME>/jre/lib/ext目錄下的JAR包中搜索要加載的類,所以,如果將包含例如Servlet API的jar包或者是javamail.jar包複製到該目錄下,在編譯Servlet或JavaMail程序時,就不必在CLASSPATH環境變量中增加包含ServletAPI的jar包或者是javamail.jar包文件。

 

附加2:關於爲什麼main()方法爲什麼要用publicstatic void修飾?

       JVM在執行java程序調用main()方法時候,不會創建這個類的實例,而是通過類名加方法名直接調用,因此需要修飾爲 public static 。另外在java中對於main()方法的使用,JVM有限制,不能有返回值(因爲這個類都沒有進行實例化,沒有能夠接受返回值的載體),因此用void修飾。

 

附加3  HelloWorld.java的另一個版本

public class HelloWorld2 {

    static {

         String s;

         s = “Hello World2!”;

         System.out.println("s = " + s);

    }

    public static void main(Stringargs[]){

        System.exit(0);

    }

}

這個版本中的main()方法執行的指令只有"System.exit(0);",目的是讓程序正常結束。那“HelloWorld!”是從哪裏打印的?其實就是在static{…….}打印的,因爲static代碼塊的內容會在main調用前調用。

個人學習心得,歡迎批評指正                                                         ------   isunnyvinson                             

                                                                                                                                                                                                            


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章