[英]Is it possible to load a class without loading referenced classes/imports?
[英]Java Class loading mechanism for referenced Classes
加載類A
,假定A
的字節碼具有對許多其他類的引用。 假設A
類如下所示。
class A extends B implements C,D {
static E e;
F f;
A() {
G g = new G();
}
void print(H h) {
}
}
JVM是否加載A
使用的所有類? 還是在類初始化之前就不用理會它們?
如果至少其中一些已加載,是否在A
完成后加載它們? 或A's
加載將暫停直到所需的類加載?
對於此問題,假定尚未加載其他任何類。 甚至是超一流的B
類和C
& D
接口。
要了解這一點,讓我們了解一些基本知識。 這將幫助任何新手了解JAVA中的延遲加載。
如果您熟悉Netscape的Web瀏覽器並且同時使用了3.x和4.x版本,那么無疑會發現Java運行時的加載方式有所不同。 如果您在Netscape 3啟動時查看啟動畫面,您會注意到它會加載各種資源,包括Java。 但是,當您啟動Netscape 4.x時,它不會加載Java運行時-它會等到您訪問包含該標記的Web頁面。 這兩種方法說明了急切的實例化(需要時將其加載)和延遲實例化(等待直到被請求之前再加載它,因為它可能永遠不需要)的技術。
這兩種方法都有缺點:一方面,如果在該會話期間未使用資源,則始終加載資源可能會浪費寶貴的內存;另一方面,如果資源在該會話期間未使用,則可能會浪費寶貴的內存。 另一方面,如果尚未加載,則需要在首次需要資源時以加載時間為代價。
將惰性實例化視為資源保護策略
Java中的延遲實例化分為兩類:
延遲類加載
Java運行時具有內置的類的惰性實例化。 類僅在首次引用時才加載到內存中。 (它們也可以首先通過HTTP從Web服務器加載。)
MyUtils.classMethod(); //first call to a static class method
Vector v = new Vector(); //first call to operator new
延遲類加載是Java運行時環境的重要功能,因為它可以在某些情況下減少內存使用。 例如,如果在會話期間從不執行程序的一部分,則永遠不會加載僅在程序的該部分中引用的類。
惰性對象創建
延遲對象的創建與延遲類的加載緊密相關。 第一次在以前尚未加載的類類型上使用new關鍵字時,Java運行時將為您加載它。 與惰性類加載相比,惰性對象的創建可以減少更多的內存使用。
為了介紹惰性對象創建的概念,讓我們看一個簡單的代碼示例,其中框架使用MessageBox來顯示錯誤消息:
public class MyFrame extends Frame
{
private MessageBox mb_ = new MessageBox();
//private helper used by this class
private void showMessage(String message)
{
//set the message text
mb_.setMessage( message );
mb_.pack();
mb_.show();
}
}
在上面的示例中,當創建MyFrame的實例時,還將創建MessageBox實例mb_。 相同的規則遞歸適用。 因此,在類MessageBox的構造函數中初始化或分配的所有實例變量也將在堆外分配,依此類推。 如果MyFrame實例不用於在會話中顯示錯誤消息,則我們不必要地浪費了內存。
在這個相當簡單的示例中,我們並不會真正獲得太多收益。 但是,如果考慮一個更復雜的類,該類使用許多其他類,這些類又依次遞歸使用和實例化更多對象,則潛在的內存使用情況會更加明顯。
public final class MyFrame extends Frame
{
private MessageBox mb_ ; //null, implicit
//private helper used by this class
private void showMessage(String message)
{
if(mb_==null)//first call to this method
mb_=new MessageBox();
//set the message text
mb_.setMessage( message );
mb_.pack();
mb_.show();
}
}
如果仔細看showMessage(),您會發現我們首先確定實例變量mb_是否等於null。 由於尚未在聲明時初始化mb_,因此Java運行時已為我們完成了此工作。 因此,我們可以安全地通過創建MessageBox實例進行操作。 以后所有對showMessage()的調用都會發現mb_不等於null,因此跳過了對象的創建並使用了現有實例。
結論 :一旦有子實體初始化,它將加載所有依賴對象。為了減少內存占用,我們應該在虛擬代理,延遲初始化等設計模式上謹慎尋找這些依賴對象。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.