<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    走在架構師的大道上 Jack.Wang's home

    Java, C++, linux c, C#.net 技術,軟件架構,領域建模,IT 項目管理 Dict.CN 在線詞典, 英語學習, 在線翻譯

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      195 Posts :: 3 Stories :: 728 Comments :: 0 Trackbacks
     

         JVM 學習筆記

    Jack.Wang(本文未完,待續…..

    摘要:JVM 作為 Java 的核心技術,很多朋友想必也有研究。一直都在關注 JVM 方面的技術,以前看過一些書籍和網上的資料,自己也發了些 Blog 文章,不過還是沒有徹底的了解 JVM 機制,最近有時間研究了研究,特此寫下一篇文章并結合筆者多年實踐以揭露 JVM 實現機理,本文后面提供資料下載,讀者可進一步研究。 

    關鍵字: JVMJava 技術,虛擬機,Java 架構

    目錄
    1 JVM架構引言 
    2 JVM安全框架 
    3 JVM內部機理 
      3.1 JVM的生命周期 
      3.2 JVM的框架 
      3.3 數據類型 
        3.3.1 Java數據類型 
        3.3.2 浮點運算 
      3.4 方法區 
      3.5 操作數棧 
      3.6 本地方法棧 
      3.7 執行引擎 
    4 類文件結構 
    5 線程同步 
    6 垃圾回收機制 
    7 總結 
    8 參考資料

    文中的圖片沒有上傳,不過想看圖片的可以下載原文。
    本文下載地址 JVM學習筆記.doc

    1          JVM架構引言

    Java 的平臺獨立,安全和網絡可移植性是的 Java 最適合網絡計算環境,java 的四大核心技術是,Java 語言,字節碼格式,Java APIJVM。每次你編寫Java程序時你就用到了這四項技術,那么你是否對他們有足夠的了解呢?

        很多人把 JVM 看成是 Java 的解釋器,這是錯誤的理解,并不是所有的 JVM 實現都 Java 的解釋器,有的也用到了 JIT (Just-In-Time) 技術。Java 是不允許直接操作本地機器指令的,對于Java方法來說有兩種:Javanative,對于native我更習慣用C++ DLL,但Java并不提倡你這么做,因為有損Java平臺獨立性。JVM 中除了執行引擎就是類加載器了,ClassLoader也分為兩種:原始加載器和加載器Object,原始加載器使用和寫JVM 一樣的語言寫的,比如用C寫的類加載器,而加載器Object就是用 Java 實現的類加載器,方便我們擴展,比如你自己可以 New 一個 URLClassLoader 從網絡上下載字節碼到本地運行。一個類的加載和他參考的類的加載應該用同一個 ClassLoader。這一點在發生異常的時候很難找出,比如 OSGI 中每個 bundle 都有自己獨立的 ClassLoader,對于新手很容易犯錯誤而無從下手,我們熟悉的WEB 服務器 Tomcat 的類加載器是分層(有繼承關系)的,所以在應用整合的時候也很容易發生 ClassLoader 相關的異常,而這樣的異常往往很難定位。平臺互異的字節序問題,在Java中,字節碼是大字節序的。Java 為支持開發者開發應用軟件提供了大量的 API,可以說,在計算機領域的大部分計算中Java都有對應的解決方案。

        C++中可能比較受關注和困擾的就是指針了,而在Java中用“參考”這樣一個類似的東西代替了,參考不向指針那樣允許參與計算,避免了開發人員直接操作內存,還有個垃圾回收機制也避免了開發者手動釋放內存,還有就是 C++ 中的數組是不進行邊界檢查的而Java中每次使用數組的時候都要進行邊界檢查,豈不安全。 可見Java相比C++ 提高了開發效率和安全性。JavaC++ 比運行速度是個大問題,因此任何語言都不萬能的,在開發是我們應該適當權衡,Java運行速度低的原因主要有:

    Ø         Interpreting bytecodes is 10 to 30 times slower than native execution.

    Ø         Just-in-time compiling bytecodes can be 7 to 10 times faster than interpreting, but still not quite as fast as native execution.

    Ø         Java programs are dynamically linked.

    Ø         The Java Virtual Machine may have to wait for class files to download across a network.

    Ø         Array bounds are checked on each array access.

    Ø         All objects are created on the heap (no objects are created on the stack).

    Ø         All uses of object references are checked at run-time for null.

    Ø         All reference casts are checked at run-time for type safety.

    Ø         The garbage collector is likely less efficient (though often more effective) at managing the heap than you could be if you managed it directly as in C++.

    Ø         Primitive types in Java are the same on every platform, rather than adjusting to the most efficient size on each platform as in C++.

    Ø         Strings in Java are always UNICODE. When you really need to manipulate just an ASCII string, a Java program will be slightly less efficient than an equivalent C++ program.

    2          JVM安全框架

    Java 允許基于網絡的代碼運行和傳播,為其帶了安全問題。但Java也提供了內嵌的安全模型,開發者可高枕無憂。Java的沙箱安全模型使即時你不信任的代碼也可讓他在本機執行,如果是惡意的代碼他的惡意行為也會被沙箱攔截,所以在運行任何你有點懷疑的代碼前請確保你的沙箱沒有缺陷。

    對于沙箱的四大基礎組件是:類加載器,類文件驗證,JVM安全特性,安全管理的API,其中最重要的是類加載器和安全管理API,因為他們可以客制化。對于加載器,每個 JVM 都可以有多個,同一個類可以加載多次到不同的 ClassLoader 中,類跨ClassLoader是不可見的,而在同一ClassLoader中是可直接訪問的,這樣可以隔離一些不安全的類。

    類型檢查是很必要的,分為兩個階段,第一是在類加載進來的時候要進行類的合法性和完整性檢查,第二是運行時確認該類所參考的類,方法和屬性是否存在。類文件頭都是以一個四個字節的幻數開頭(0xCAFEBABE)來標識是個類文件,當然也有文件大小域,第一階段確保加載進來的類是正確格式,內部一直,Java語法語義限制一直,包括安全的可執行代碼,在這個過程中如果有錯誤,JVM會拋出異常,該類就不會被使用。第二階段其實由于動態連接的原因,需要在運行時檢查參考,因為 ClassLoader 在需要某些類時才去加載,延遲加載,在 ORM 產品中,比如 Hibernate, jdo 等都有所謂的延遲加載

    SecurityManager 有一系列的 checkXXX 的方法,用來檢測相關操作是否合法,一般我們的程序是不用 SecurityManager 的,除非你安裝一個SecurityManager,如果沒有寫自己的策略文件,一般是用jre 下面的默認策略文件的設置,當然也可在 VM 運行參數設置策略文件的位置。SecurityManager 類的相關方法。

        publicstatic SecurityManager getSecurityManager() {

        return security;

        }

       publicstatic

        void setSecurityManager(final SecurityManager s) {

            try {

                s.checkPackageAccess("java.lang");

            } catch (Exception e) {

                // no-op

            }

            setSecurityManager0(s);

        }

        privatestaticsynchronized

        void setSecurityManager0(final SecurityManager s) {

        SecurityManager sm = getSecurityManager();

            if (sm != null) {

            // ask the currently installed security manager if we

            // can replace it.

            sm.checkPermission(new RuntimePermission

                       ("setSecurityManager"));

        }

        if ((s != null) && (s.getClass().getClassLoader() != null)) {

            AccessController.doPrivileged(new PrivilegedAction() {

           public Object run() {

               s.getClass().getProtectionDomain().implies

               (SecurityConstants.ALL_PERMISSION);

               returnnull;

           }

            });

        }

    security = s;

    InetAddressCachePolicy.setIfNotSet(InetAddressCachePolicy.FOREVER);}

    設置自己的 SercurityManager:

    System.setSecurityManager(new JackSecurityManager());

    SecurityManager sm = System.getSecurityManager();

    3          JVM內部機理

    3.1         JVM的生命周期

    任何一個類的 main 函數運行都會創建一個JVM實例,當main 函數結束JVM實例也就結束了,如果三個類分別運行各自的 main 函數則會創建3個不同的JVM實例。JVM實例啟動時默認啟動幾個守護線程,而 main 方法的執行是在一個單獨的非守護線程中執行的。只要母線程結束,子線程就自動銷毀,只要非守護main 線程結束JVM實例就銷毀了。

    3.2         JVM的框架

    JVM主要由 ClassLoader 子系統和執行引擎子系統組成,運行數據區分為五個部分,他們是方法區,堆,棧,指令寄存器,本地方法棧。方法區和堆是所有線程共享的,一般我們習慣對臨時變量放在寄存器中,但JVM中不用寄存器而是用棧,每個線程都有自己獨立的棧空間和指令計數器,其中棧里的元素叫幀,幀有三部分組成分別是局部變量,操作數棧和幀數據。正式因為棧是每個線程獨有的,所以對于 local 變量,是沒有多線程沖突問題的。棧和幀的數據結構和大小規范里沒有硬性規定,由實現者具體實做。

    3.3         數據類型

    3.3.1   Java數據類型

            

    虛擬機的數據類型分為:原始類型和參考類型,有人一直說Java只有90%OO的,其中原始類型就算的上,不過還好有對應的封裝類型如 int->IntegerJDK1.5可以用這些封裝類型直接做算術運算,不過Java內部要做拆箱和裝箱的工作。似乎   OO了些,不過現代的程序員才不過你這些,能用就行。

    字長是數據值得基本單元,一般像 int, byte, short 等類型的值用一個字長存儲,而浮現類型用兩個字長存儲,字長的大小一般和機器的指針大小相同,最小是32 位。

    byte, short, or char 這樣的類型在方法區和堆中Java是原來類型,但在程序運行時放在棧幀中,統一用整型(int)來表示

    對于類型之間的轉換JVM有對應的指令如:

    上圖是小范圍向大范圍轉變,叫做向上轉型,當然也有向下轉型的指令,不過可能會造成數據被破壞,如圖:

    不管你怎么變化,棧幀里都是以字為單位的,32位機子一個字是4個字節,正好是一個整型大小,如前所述原始類型在棧中都被表示為 int 型,當然如果是 long double 那就用兩個字來表示咯。

    3.3.2   浮點運算

    浮點運算算法因該是倍受關注的了,Java中浮點數的表示遵照IEEE 754 1985的規范,這個規范定義了32位和64位浮點格式和運算,我都知道Java中的 float 32位而,double64位。對于浮點數大家都很清楚他分為四個部分:符號,尾數,基數和冪,要得到浮點數值必須將這四個部分相乘才能得到值。所有的浮點數都要經過標準化,我們都知道計算機里只有01這樣的表示,尾數和冪都要二進制表示,對于尾數float 用它的23位表示,double 用它的52位來表示,對于冪數 float 用它的 8位表示,double用它的11為表示,剩下以為表示符號。

         JVM也有對應的浮點運算指令如圖(加法指令)

    3.4         方法區

    ClassLoader負責把class加載進來并解析類信息放在方法區,方法區是被所有線程共享的,所以方法區必須保證線程的安全。比如兩個線程同時需要一個類,必須保證只有一個線程去加載而另一個線程等待。

    方法區的大小不是固定的,一般會在運行時JVM會根據運行情況作出調整,但JVM實現者都留有接口可供調節,比如最大和最小值。

    我們都知道堆是被垃圾回收器回收的,在方法區的類也是會被回收的,類也有他的生命周期,當某個類不再被參考之后也就沒有這個類的引用和對象了那么他的存在就沒有意義了,只是站著內存,回收器就會按照一定的算法將它卸載了。對于一個類信息的表述都是用全名的,在方法區中也有其他信息,比如常量池,屬性和方法信息,還有就是指向堆中的 ClassLoaderClass 的參考。我大家都熟悉的就是類的靜態變量,也放在方法區的由所有的對象實例共享。

    可以想象在方法區內放置了大量的二進制的Class信息,為了加快訪問速度,JVM實現者都會維護一個方法表,記得讀研一的時候中間件老師講過這些東西是結合指針講的C++ 的內存模型。另外注意的就是方法表只針對可實例化的類,對抽象類和接口沒有意義。

    每個JVM實例都只有一個堆,所有的線程共享其中的對象,這才出現了多線程安全問題。JVMnew 對象的指令但沒有釋放對象的指令,當讓這些指令都是虛擬指令,這些對象的釋放是有 GC 來做的,GCJVM規范中并沒有硬性的規定,有實現者設計他的實現形式和算法。

    想必很多同人都想知道,對象是怎么樣在堆里表示的,其實很簡單。其實面JVM規范也沒有細致的規定對象怎么在堆里表示的,

    如圖是一個參考的堆模型,具體實現可能不是這樣的,這個是HeapOfFish applet 的一個演示模型,具體內容可以看看JVM規范。當然也有很多其他的模型,這個模型的好處就是在堆壓縮的時候很方便,而在 reference 直接 point到一個對象的模型來說在堆壓縮方面是很麻煩的,因為你要考慮到方法區,堆,棧里可能的參考,你都要修改。對象還有一個很重要的數據結構就是方法表,方法表可以加快訪問速度,但并不是說所有的JVM實現都有。

    堆中的每個對象都有指向方法區的指針,而自己主要保留對象屬性信息,如圖:

    看一個方法區鏈接的例子,看看一個類是怎么加載進來,怎么鏈接初始化的:

    有一 Salutation 類

    class Salutation {

        private static final String hello = "Hello, world!";

        private static final String greeting = "Greetings, planet!";

        private static final String salutation = "Salutations, orb!";

        private static int choice = (int) (Math.random() * 2.99);

        public static void main(String[] args) {

            String s = hello;

            if (choice == 1) {

                s = greeting;

            }

            else if (choice == 2) {

                s = salutation;

            }

            System.out.println(s);

        }

    }

    Assume that you have asked a Java Virtual Machine to run Salutation. When the virtual machine starts, it attempts to invoke the main() method of Salutation. It quickly realizes, however, that it canít invoke main(). The invocation of a method declared in a class is an active use of that class, which is not allowed until the class is initialized. Thus, before the virtual machine can invoke main(), it must initialize Salutation. And before it can initialize Salutation, it must load and link Salutation. So, the virtual machine hands the fully qualified name of Salutation to the primordial class loader, which retrieves the binary form of the class, parses the binary data into internal data structures, and creates an instance of java.lang.Class.

    常量池里的內容:

    Index

    Type

    Value

    1

    CONSTANT_String_info

    30

    2

    CONSTANT_String_info

    31

    3

    CONSTANT_String_info

    39

    4

    CONSTANT_Class_info

    37

    5

    CONSTANT_Class_info

    44

    6

    CONSTANT_Class_info

    45

    7

    CONSTANT_Class_info

    46

    8

    CONSTANT_Class_info

    47

    9

    CONSTANT_Methodref_info

    7, 16

    10

    CONSTANT_Fieldref_info

    4, 17

    11

    CONSTANT_Fieldref_info

    8, 18

    12

    CONSTANT_Methodref_info

    5, 19

    13

    CONSTANT_Methodref_info

    6, 20

    14

    CONSTANT_Double_info

    2.99

    16

    CONSTANT_NameAndType_info

    26, 22

    17

    CONSTANT_NameAndType_info

    41, 32

    18

    CONSTANT_NameAndType_info

    49, 34

    19

    CONSTANT_NameAndType_info

    50, 23

    20

    CONSTANT_NameAndType_info

    51, 21

    21

    CONSTANT_Utf8_info

    "()D"

    22

    CONSTANT_Utf8_info

    "()V"

    23

    CONSTANT_Utf8_info

    (Ljava/lang/String;)V"

    24

    CONSTANT_Utf8_info

    ([Ljava/lang/String;)V"

    25

    CONSTANT_Utf8_info

    <clinit"

    26

    CONSTANT_Utf8_info

    <init"

    27

    CONSTANT_Utf8_info

    "Code"

    28

    CONSTANT_Utf8_info

    "ConstantValue"

    29

    CONSTANT_Utf8_info

    "Exceptions"

    30

    CONSTANT_Utf8_info

    "Greetings,planet!"

    31

    CONSTANT_Utf8_info

    "Hello, world!"

    32

    CONSTANT_Utf8_info

    "I"

    33

    CONSTANT_Utf8_info

    "LineNumberTable"

    34

    CONSTANT_Utf8_info

    "Ljava/io/PrintStream;"

    35

    CONSTANT_Utf8_info

    "Ljava/lang/String;"

    36

    CONSTANT_Utf8_info

    "LocalVariables"

    37

    CONSTANT_Utf8_info

    "Salutation"

    38

    CONSTANT_Utf8_info

    "Salutation.java"

    39

    CONSTANT_Utf8_info

    "Salutations, orb!"

    40

    CONSTANT_Utf8_info

    "SourceFile"

    41

    CONSTANT_Utf8_info

    "choice"

    42

    CONSTANT_Utf8_info

    "greeting"

    43

    CONSTANT_Utf8_info

    "hello"

    44

    CONSTANT_Utf8_info

    "java/io/PrintStream"

    45

    CONSTANT_Utf8_info

    "java/lang/Math"

    46

    CONSTANT_Utf8_info

    "java/lang/Object"

    47

    CONSTANT_Utf8_info

    "java/lang/System"

    48

    CONSTANT_Utf8_info

    "main"

    49

    CONSTANT_Utf8_info

    "out"

    50

    CONSTANT_Utf8_info

    "println"

    51

    CONSTANT_Utf8_info

    "random"

    52

    CONSTANT_Utf8_info

    "salutation"

    As part of the loading process for Salutation, the Java Virtual Machine must make sure all of Salutationís superclasses have been loaded. To start this process, the virtual machine looks into Salutationís type data at the super_class item, which is a seven. The virtual machine looks up entry seven in the constant pool, and finds a CONSTANT_Class_info entry that serves as a symbolic reference to class java.lang.Object. See Figure 8-5 for a graphical depiction of this symbolic reference. The virtual machine resolves this symbolic reference, which causes it to load class Object. Because Object is the top of Salutationís inheritance hierarchy, the virtual machine and links and initializes Object as well.

    3.5         操作數棧

    操作數棧是Java運行時的核心棧,看看 i+j 的一個簡單運算,

    iload_0  

    iload_1   

    iadd      

    istore_2 

    以上是四個JVM指令,完成 i+j并把結果保存到k中,如圖示:

    在堆中不可能分配一個原始類型的空間放值,而是先用對象封裝才能存在堆空間中,帶Java棧中也不可能放對象,而只有原始類型和參考類型。上次有人爭議數組放在何處?在Java中數組和對象是同等地位的,都放在堆中而他的參考是放在棧里,JVM有對應的指令比如 newarray, anewarray等。

    3.6         本地方法棧

    想必很多人用過 JNI 結束,Java是不提倡這么做的,而且在這放的設計和實現上,個人覺得不是那么好,至少他比不那么方便,所以很少見應用開發者去寫些 Native 方法,每次你去看Java原代碼是你經常看到native 方法,也看到JDK下的 DLL 文件,大部分JVM都是用CC++寫的。前面也提過,這樣就破壞了Java的平臺獨立性,在本地方法運行的時候也有專門的棧去處理。Java在執行本地方法的時候暫時放棄Java stack 的操作,轉向本地方法,本地方法有自己的棧或堆的處理方式,Java在執行本地方法時會在本地棧和Java棧之間切換,如圖:

    a thread first invoked two Java methods, the second of which invoked a native method. This act caused the virtual machine to use a native method stack. In this figure, the native method stack is shown as a finite amount of contiguous memory space. Assume it is a C stack. The stack area used by each C-linkage function is shown in gray and bounded by a dashed line. The first C-linkage function, which was invoked as a native method, invoked another C-linkage function. The second C-linkage function invoked a Java method through the native method interface. This Java method invoked another Java method, which is the current method shown in the figure,做過JNI開發的朋友應該了解JavaCC++ 是如何交互的,這些都是執行引擎的事。

    3.7         執行引擎

    執行引擎,應該是JVM的核心了,一般我把它看作指令集合。JVM規范詳細的描述了每個指令的作用,但沒有進一步描述如何實現,還由實現廠商自己設計,可以用解釋的方式,JIT方式,編譯本地代碼的方式,或者幾者混合的方式,當然也可用一些新的不為我們知道的技術。

    每一個線程都有一個自己的執行引擎,據我了解JVM指令用一個字節表示,也就是JVM最多有256個指令,目前JVM已有160(目前可能多于這些)個指令。就有這百十個指令組成了我的系統,JVM指令一般只有操作碼沒有操作數,一般操作數放在常量池和Java棧中,設計指令集的最重要的目標應該是平臺獨立性,同時在驗證bytecode也比較方便。有些指令的操作都是基于具體類型的,有的就沒有比如 goto,如圖

    指令前綴表示操作類型, 可見Java編譯器和JVM對類型操作要求很嚴格,為何使指令盡量用一個字節表示,很多類型如 byte, char 都沒有直接運算,而是在運算前把他們轉換成整型。

    執行過程的在某一時刻內容如圖:

    在幀里的局部變量有四個分別都是 reference,都指向不同的對象,有的時候我們編程當操作完成,最好把 o, greeter ,c, gcl  這四個參考付為 null,這樣他們指向的對象不可達,對象不可達,他們在方法區的類信息也不可達,類信息不可達,堆中的 Class 對象不可達,你可以看到圖中的所有對象,類信息都是可回收狀態,這樣GC某個時刻就可以釋放了這些內存了。

    寫方法時我們希望 try cache 起來,當然也有需要在后面 加上 finally,我們都知道在finally 里的代碼被執行玩前所有的 return 操作都會壓入棧里,等 finally塊執行完了再彈出返回,如:

    static boolean test(boolean bVal) {

    while (bVal) {

    try {

    return true;

    }

    finally {

    break;

    }

    }

    return false;

    }

    可以看出這個方法的執行以返回 false 告終。

    4          類文件結構

    讀者可以用 UltrEdit 之類的編輯工具打開一個 class 文件查看,每個類文件都包含如下內容如圖:其中 u2 表示兩個字節大小,u4表示四個字節大小。

    如第一行所示,每個類文件都以幻數開頭固定為(0xCAFEBABE),用UltraEdit 等編輯工具可以直接看到,當然你也可以看到很多如圖所示的屬性和方法的描述:

    常量池是以類型來劃分不同的表格的,如CONSTANT_Double_info 表就只是double 常量值,CONSTANT_Class_info表存儲參考信息,比如類,接口,屬性和方法的符號參考,類文件的核心數據結構就是常量池了,而所有的類,屬性和方法的描述以及值都是通過 index 到常量池獲得的,所以常量池是個很重要的概念,有興趣的朋友可進一步參考JVM規范。

    5          線程同步

            對多線程的支持是java 語言的一大亮點,java 實現線程同步的方式是monitor,具體有兩種方式:互斥和協同,每個對象都有一把鎖,通過 lock 和 unlock 實現互斥的操作,Object類有 wait notify 等這樣的方法可以實現線程為實現一個共同的目標而協同工作。monitor就像一個建筑有一個特殊的房間每次只允許一個線程訪問。都知道線程同步有一個重要的概念就是臨界區,任何一個線程要想進入臨界區就必須獲得monitor,如果線程發現monitor被其他線程獲得,此線程必須排隊,等到他前面的線程也退出了 monitor 的占有,則此線程才能操作 monitor 的臨界區,當然也有優先級 的問題。此圖說明了多個線程協作工作的過程。

            前面介紹過,堆和方法區是被線程共享的,這兩大塊要做同步,而對于局部變量是由線程獨有的所以不存在同步問題,Java API 中有一個很重要也很簡單的類就是 ThreadLocal,他是用 Theard key 來標識變量,是非局部變量局部化的一個很好的例子。

            對象鎖的概念大家都很熟悉了,Java中通過這個鎖有兩種方式,一種是同步塊,一種是同步方法,具體的內容請看看java 多線程編程的書。

    6          垃圾回收機制

              堆里聚集了所有由應用程序創建的對象,JVM也有對應的指令比如 new, newarray, anewarraymultianewarray,然并沒有向 C++ deletefree 等釋放空間的指令,Java的所有釋放都由 GC 來做,GC除了做回收內存之外,另外一個重要的工作就是內存的壓縮,這個在其他的語言中也有類似的實現,相比 C++ 不僅好用,而且增加了安全性,當然她也有弊端,比如性能這個大問題。

    垃圾回收的算法有很多,不過怎么樣,任何一個算法都要做兩件事情,一是識別垃圾對象,二是清理內存以備運行程序使用。區分活著的對象和垃圾對象的主要方法就是參考計數和追蹤,參考計數就是每個對象都維護一個引用 count,而每次追蹤都去標記對象,當一次跟蹤完成沒有被標記的對象就是不可到達的那就是垃圾了。參考計數的方式現在已經很少JVM實現用了,因為對于 child, parent 的內部參考,count 永遠不會是0,也就是不會是垃圾對象,而且每次修改引用都要加減 count。而跟蹤是從根節點開始掃描所有對象,并作標記。知道那些對象是垃圾了之后,就要釋放了,有兩種方式一個是壓縮,一個是拷貝,不管哪種方式改變了對象的物理位置,就要修改他的參考值,每個對像都有一個 finalize 方法,一般我們不去 override 他,他是在回收時期執行,但并不是所有的對象的 finalize 方法都會被執行,具體內容請看 inside in java machine.

    7          總結

    本文結合作者的一些觀點和幾年的開發實踐,談談對JVM規范的看法,由于完稿倉促,也沒多少時間整理,如果有什么問題可以進一步討論,本人編譯器這方面也是比較薄弱,真正按照JVM規范實現虛擬機還有很長的路要走,可能在將來的某天有機會進一步研究一下。多謝各位的指導和幫助,我會陸續在Blog里發些文章。

    8          參考資料

    1)inside in java machine 想要的請點擊下載

    2)http://www.tkk7.com/Jack2007/archive/2008/05/23/202485.htmlJava虛擬機深入研究

    3)http://www.tkk7.com/Jack2007/archive/2008/05/21/202018.html

    4)http://www.tudou.com/programs/view/hN_4sQJMoFQ/

    5)http://www.tkk7.com/Jack2007/archive/2008/04/11/192288.html

    6)http://developer.51cto.com/art/200805/73338.htm

     





    本博客為學習交流用,凡未注明引用的均為本人作品,轉載請注明出處,如有版權問題請及時通知。由于博客時間倉促,錯誤之處敬請諒解,有任何意見可給我留言,愿共同學習進步。
    posted on 2008-08-27 15:18 Jack.Wang 閱讀(6835) 評論(5)  編輯  收藏 所屬分類: 開發技術

    Feedback

    # re: JVM 學習筆記 2008-08-28 00:11 流浪汗
    比如兩個線程同時需要一個類,必須保證只有一個線程去加載而另一個線程等待。

    我不在認為正確, 方法區是共用, 但運行時, 方法調用的時候有自己的數據區, 除非那變量是類的(static), 否則保證object線程完全就行了.  回復  更多評論
      

    # re: JVM 學習筆記 2008-08-28 11:48 zhuxing
    java虛擬機對類加載本身就做了同步處理。!!!

    同一個類加載器實例不可能對同一類型加載多次
    不同的類加載器實例可能會對同一全名類型記載多次,那本質上是不同的類型了,類加載器實例一個很核心的作用就是來維護命名空間  回復  更多評論
      

    # re: JVM 學習筆記 2008-08-28 17:21 Swing
    ORM中的延遲加載似乎指的是對象不是類吧?  回復  更多評論
      

    # re: JVM 學習筆記 2008-08-29 12:21 隔葉黃鶯
    一個 JVM 可以由多個 ClassLoader 加載同一個類,所以說在同一個 JVM 中一個類靜態變量可以表現為多個值,但它們是互不可見的,所以仍不會影響到真正的使用。在 JVM 中對象有對象的實例,類有類的實例,比如
    Class1 obj1,obj2; 對象實例是不一樣的,但同們的類實例 obj1.getClass() 是一樣的,前提是它們都是委派給同一個 ClassLoader 加載的

    字長的大不應該是由 JVM 的統一,比如在 64 位 CPU 中運行的 32 位 JVM,最小字長這時候會是多少呢?Java 要由不跨平臺的 JVM 來保證跨平臺。

    ORM 的延遲加載應該是在對象層面的概念,提前加載的是是目標對象的代理對象。

    像 Groovy 那樣的腳本會是更純粹面向對象

    def i = 1; 打印出 i.getClass(); 會顯示為 class java.lang.Integer

    在棧幀中,不光是 byte, short, char 表現為 int,而且 boolean 也是用 int 來表示

    我想,大家都習慣用引用來表示“參考”

    寫得不錯,就是有不少錯別字。

    順便問一下,讀研若之前沒有積蓄能不能完全養活自己,不然靠老婆養可沒面子哦,呵呵!  回復  更多評論
      

    # re: JVM 學習筆記 2008-08-29 12:53 Jack.Wang
    @隔葉黃鶯
    本文只是亂打的草書,沒有細致的分析,所以錯別字太多。
    考研當然要有積蓄。學費+生活費要幾萬塊啦,在加上兩三年不賺錢,對于我們工作的人來說,損失幾十萬啊!不過自己選擇的路,就應該好好走下去。
      回復  更多評論
      

    主站蜘蛛池模板: 2020久久精品亚洲热综合一本| 亚洲黄片手机免费观看| 亚洲熟妇av一区二区三区漫画| 精品香蕉在线观看免费| eeuss影院免费92242部| 亚洲精品无码久久久久APP| 婷婷精品国产亚洲AV麻豆不片| 哒哒哒免费视频观看在线www | 国产精品极品美女免费观看 | 亚洲AV福利天堂一区二区三| 免费午夜爽爽爽WWW视频十八禁| 国产情侣激情在线视频免费看| a级毛片毛片免费观看久潮| 香蕉国产在线观看免费| 欧美亚洲国产SUV| 亚洲av无码专区在线观看下载 | 最近免费中文字幕大全| 182tv免费观看在线视频| 最近中文字幕大全免费版在线 | 国产一精品一AV一免费孕妇| 69免费视频大片| 在线观看免费无码专区| AAAAA级少妇高潮大片免费看| 未满十八私人高清免费影院| 日韩国产欧美亚洲v片| 亚洲日本VA午夜在线电影| 亚洲av无码一区二区三区天堂古代| 亚洲av色影在线| 久久久久久久久亚洲| 亚洲Aⅴ无码专区在线观看q| 亚洲精品国产精品乱码不卡√| 亚洲一本大道无码av天堂| 亚洲av午夜成人片精品电影 | 一级毛片免费全部播放| 一级黄色片免费观看| 色婷婷综合缴情综免费观看| sss日本免费完整版在线观看| h视频免费高清在线观看| 91福利免费网站在线观看| 国产免费网站看v片在线| 亚洲一区免费观看|