1. 程式人生 > >背的(最基本的)

背的(最基本的)

slide 動態鏈接 放棄 利用 出棧 simple pan 創建 因此

註:藍色高亮代表還要查寫的東西;紅色字體用於閱讀時提醒

----------------------------------------------------Hello!-----------------------------------------------------------How-----------------------------------------------------------------are----------------------------------------------------------------------------------you?------------------------------------------------------------------------

Q:請解釋PATH和CLASSPATH的區別?

A:PATH是系統定義的環境屬性,用於定義所有可執行程序的路徑;

CLASSPATH是JVM定義的屬性,在用java命令解釋程序時會自動找到CLASSPATH的路徑,進行類的加載。

對象內存分析

  類本身屬於引用數據類型,對於引用數據類型,必須對其進行內存分析。

  堆內存:保存的是對象的具體屬性信息;

  棧內存:保存堆內存的地址(可理解為:對象名稱)。

  一塊棧內存只能保存一塊對應的堆內存地址。

技術分享圖片

第二種定義方法

  Person per=null;//聲明對象

  per=new Person();//實例化對象

當沒有實例化時,運行會發生 NullPointException;因為使用了沒有開辟堆內存空間的引用對象。

(1)一塊堆內存空間可以被多個棧內存所指向;

(2)如果一塊堆內存空間沒有任何棧內存指向,它會變成垃圾空間,所有垃圾空間會被GC回收並釋放。垃圾回收時間時不確定的,要少產生。

構造方法:

  方法名稱與類名稱相同;

  如果一個類中沒有構造方法,系統會自動提供一個無參構造。(所以,所有類中,肯定都有構造方法)。

  作用:如果希望在對象實例化時傳遞一些參數,可用。

  Q:既然構造方法沒有返回值,那為什麽不用void聲明?

  A:構造方法只在對象聲明時調用一次;不同方法可以利用對象調用多次,如果是public void Person(){};這表示一個普通方法。

static:

  主要用於描述全局概念;修改一個對象屬性時,所有對象屬性都會發生改變。對於這樣的公共屬性,不保存在棧,堆中,而保存在全局數據區中。

  對於static定義的屬性,可以用類名稱直接調用。

  所有非static屬性,在對象實例化的時候才會進行內存的分配;

  所有static屬性,可以在沒有實例化對象的時候進行調用。

  使用情況:如果一個類中沒有任何屬性,那麽這個類中不需要定義普通方法,只需要定義static方法。因為這樣可以減少開辟無用的堆內存空間。

單例模式:

  1.將該類的構造方法私有化,目的是禁止其他程序創建該類的對象;

  2.在本類中自定義1個對象:

  3.提供一個訪問該類自定義對象的成員方法。

線程的幾種可用狀態:

  1.新建;

  2.可運行(runnable):線程對象創建後,其他線程(比如main)調用了該對象的start()方法,該線程位於可運行線程池中,等待被線程調度選中,獲得CPU適用權;

  3.運行(running):可運行的線程獲得CPU的時間片(timeslide),執行程序代碼;

  4.阻塞(block):線程因為某原因放棄了CPU的適用權。阻塞分三種:

    4.1等待~,運行的線程執行o.wait()方法,JVM會把該線程放入等待隊列中;

    4.2同步~,運行的線程在獲取同步鎖時,該同步鎖被別的線程占用,JVM會把線程放到鎖池中;

    4.3其他~,運行的線程執行Thread.sleep(Long ms)或t.join();

  5.死亡:線程run()或main()方法結束,或者由於異常退出了run()。死亡的線程不可再次復生。

死鎖:

  兩個或以上的線程在執行過程中,因爭奪資源而造成的一種相互等待現象。

  產生原因:系統資源不足;進程運行順序不合適;資源分配不當;

  死鎖的4個必要條件:

    互斥,一個資源每次只能被一個進程使用;

    請求與保持,1個進程因請求資源而阻塞,對以獲得的資源保持不放;

    不可剝奪:進程已獲得的資源,在未使用完成前不能強行剝奪;

    循環等待:若幹線程形成一種頭尾相接的循環等待資源關系;

-------------------------------------------------------------------------------------------------------------------------------------------------------------:)-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

// 垃圾回收這裏又忘了,把印象筆記裏的重新抄一篇。完整版請參閱:http://blog.csdn.net/u012422829/article/details/46580893

java內存區域分析

  1.運行時數據區域分析

    運行時數據區域分為兩部分,一部分時線程共享的(方法區,堆),另一部分時線程私有的(虛擬機棧,本地方法棧,程序計數器)

    技術分享圖片

    (1) 程序計數器:一塊較小的內存空間,可看作是,當前線程所執行的字節碼的行號指示器

     如果線程正在執行一個Java方法,計數器值為當前執行時虛擬機字節碼指令地址;如果執行的時native方法,計數器值為空。

    (註:被native修飾的方法叫本地方法,本地方法意味著和平臺有關,移植性不高,native方法在JVM運行時數據區和其他方法不一樣,它有專門的本地方法棧。native方法主要用於加載文件和動態鏈接庫。是唯一不會出現OutOfMemoryError的區域)

    (2)虛擬機棧:描述的是Java方法執行時的內存模型。

    每個方法方法執行時都會創建一個棧幀,用於存儲局部變量,操作數棧,動態鏈接,方法出口等信息。每個方法從調用到執行完的過程,都對應一個棧幀在虛擬機中入棧到出棧的過程。

    (3)本地方法棧:作用與虛擬機棧類似。

    區別:虛擬機棧為虛擬機執行Java方法(也就是字節碼)服務,本地方法棧為虛擬機使用到的native方法服務,也會拋出StackOverFlowError和OutOfMemoryError異常

    (4) java堆:被所有線程共享,在虛擬機啟動時創建,它的目的是存放對象實例,幾乎所有對象(和數組)都在這裏分配內存。java堆是垃圾收集器管理的主要區域,也被稱為GC堆。~處於物理上不連續的內存空間,只要邏輯上連續即可。

    (5)方法區:所有線程共享,存儲已被虛擬機加載的類信息,常量,靜態變量,及時編譯器編譯後的代碼數據。雖然有”永久代“之稱,任然存在內存回收,主要針對常量池的回收和對類型的卸載,也會拋出OutOfMemoryError異常。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------O_o------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

對象的創建

  虛擬機遇到new指令時,先檢查虛擬機是否加載了你要new的這個類(檢查這個指令的參數能否在常量池中定位到一個類符號的引用),如果沒加載,必須先執行相應的類的加載。

  然後,為新生對象分配內存。

  內存分配之後,虛擬機需要將內存空間都初始化為0。

  接下來,對對象做必要的設置,例如,這個對象是哪個類的實例?如何才能找到類的元數據信息,對象的哈希碼等,這些信息都存放在對象的頭之中。

  最後,執行程序員的意願初始化。

類的加載機制

  虛擬機把描述類的數據從class文件加載到內存中,並對數據進行校驗,轉換解析和初始化;最終形成可以被虛擬機直接使用的Java類型,這就是虛擬機的類加載機制

  在Java中,類的加載,連接和初始化過程都是在程序運行期間完成的。

  類從被加載到虛擬機內存中開始,到卸載出內存為止,整個生命周期包括:加載,【驗證,準備,解析】(註:這三個動作稱為:連接),初始化,使用和卸載。註:解析的順序不是固定的,有時候能在初始化結束後才開始,以支持Java動態綁定

下面寫初始化時機

類加載過程:

  1.加載

該階段要完成以下三件事:

  (1)通過一個類的全限定名來獲取此類的二進制流

  (2)將這個字節流所代表的靜態存儲結構轉化為方法區運行時的數據結構

  (3)在內存中生成一個代表這個類的java.lang.Class對象,作為方法區這個類的各種數據的訪問入口

  2.驗證

目的是為了確保Class文件的字節流中包含的信息符合當前虛擬機的要求,因為Class文件的來源不一定時編譯產生。甚至可以直接用十六進制編輯器直接編寫。所以,如果不檢查輸入的字節流,對其完全信任的話,很有可能因為載入有害的字節流而導致系統崩潰

(大致可以分為4個階段的檢驗 :1.文件格式驗證 2.元數據驗證 3.字節碼驗證 4.符號驗證)

  3.準備

是正式為類變量(被static修飾的變量)設置類變量的初始值(通常情況下數據類型值為0,具體賦值階段時初始化階段)。這些變量所使用的內存都將在方法區中進行分配,如果字段屬性表中包含ConstantValue屬性,那麽準備階段會設置為該值。

例如:public final static int a =123;

  4.解析

是虛擬機將常量池中的符號引用替換為直接引用的過程

在Java中,一個Java類會編譯成一個class文件,在編譯時Java類並不知道引用類的實際地址,因此只能使用符號引用來代替。比如:org.simple.People類引用org.simple.Tool類,在編譯時People類並不知道Tool類的實際內存地址,因此只能使用符號org.simple.Tool(假設)來表示Tool類的地址。而在類裝載器裝載People類時,此時可以通過虛擬機來獲取Tool類的實際內存地址。因此便可以將符號org.simple.Tool替換為Tool類的實際地址,即直接引用。(註:直接引用與虛擬機實現的內存布局相關,引用目標必須加載到內存中;符號引用則不必須)。  

  5.初始化

在之前的階段,除了加載階段用戶可以自定義類加載參與,其他階段完全由虛擬機主導和控制,直到初始化階段,才真正執行類定義的Java程序代碼。

虛擬機設計團隊把類加載階段中的“通過一個類的全限定名來獲取此類的二進制字節流”這個動作放到Java虛擬機外部去實現,以便讓應用程序自己決定如何獲取所需要的類。實現這個動作的代碼模塊稱為類加載器

背的(最基本的)