前言
最近在ITeye上看見一些朋友正在 激烈 討論關于Java7.x的一些 語法結構 ,所以筆者有些手癢,特此 探尋 了7.x(此篇博文筆者使用的是目前最新版本的JDK-7u15)的一些 新特性 分享給大家。雖然目前很多開發人員至今還在沿用Java4.x(筆者項目至今沿用4.x),但這并不是成為不前進的 借口 。想了解Java的發展,想探尋Java的未來,那么你務必需要時刻保持一顆永不落后的 心 。
?
當然筆者此篇博文 并 不代表官方觀點 ,如果有朋友覺得筆者的話語是妙論,希望指正提出,筆者會在第一時間糾正博文內容。在此筆者先謝過各位利用寶貴的時間閱讀此篇博文,最后筆者祝愿各位新年大吉,工作順利。再次啰嗦一點, SSJ的系列博文,筆者將會在本周更新 ,希望大家體諒。
?
目錄
一、自動資源管理;
二、“<>”類型推斷運算符;
三、字面值下劃線支持;
四、switch字面值支持;
五、聲明二進制字面值;
六、catch表達式調整;
七、文件系統改變;
八、探討Java I/O模型;
九、Swing Framework(JSR 296規范)支持;
十、JVM內核升級之Class Loader架構調整;
十一、JVM內核升級之Garbage Collector調整(時間倉促,后期講解);
?
一、自動資源管理
早在7.x版本之前,某些可回收資源比如:I/O鏈接、DB連接、TCP/UDP連接。開發人員都需要在使用后對其進行 手動 關閉,如果不關閉或者忘記關閉這些資源,就會長期 霸占 JVM內部的資源,極大程度上 影響 了JVM的資源分配。就像內存管理一樣,開發人員夢寐以求的就是希望有一天再也無需關注 繁瑣 的資源管理(資源創建、資源就緒、資源回收)。值得慶幸的是7.x為我們帶來了一次徹頭徹尾改變,我們將再也不必以手動管理我們的資源。
早在Java5.x的時候,Java API為開發人員提供了一個Closeable接口。該接口中包含一個close()方法,允許所有可回收資源的類型對其進行重寫實現。7.x版本中幾乎所有的資源類型都實現了Closeable接口,并重寫了close()方法。也就是說所有可回收的系統資源,我們將 再 不必 每次使用完后調用close()方法進行資源回收,這一切全部交接給自動資源管理器去做即可。
例如Reader資源類型繼承Closeable接口實現資源自動管理:
public abstract class Reader implements Readable, Closeable
??
當然如果你需要在程序中使用自動資源管理,還需要使用API提供的新語法支持,這類語法包含在try語句塊內部。看到這里你可能不禁感嘆,try也能 支持表達式 了,是的7.x確實允許try使用表達式的 語法方式 實現自動資源管理,但 僅限 于資源類型。
使用try表達式實現自動資源管理:
try(BufferedReader reader = new BufferedReader(new FileReader("路徑"));) { //... } catch(Exception e) { e.printStackTrace(); }
??
? 二、“<>”類型推斷運算符
Java 5.x 新增了許多新的功能,在這些新引入的功能中,泛型最為 重要 。泛型是一種新的語法元素,泛型的出現導致整個 Java API 都發生了變化( 比如: Java 集合框架就使用了泛型語法)。
在泛型沒有出現之前,我們都是將 Object 類作為通用的 任意數據類型 使用。因為在 Java 語言中, Object 類是所有類的超類 。但是使用 Object 類作為任意數據類型并不是安全的,因為在很多時候我們需要將 Object 類型向下轉換,在這些轉換過程中偶爾也可能出現 不匹配 的類型轉換錯誤。泛型的出現則很好的解決了 Object 類型所存在的 安全性 問題,且泛型還擴展了代碼的重用性。
泛型的核心概念就是 參數化類型 ,所謂參數化類型指的就是開發人員可以在 外部 指定的數據類型來創建泛型類 、 泛型接口和泛型方法。
使用泛型類型示例:
List<String> list = new ArrayList<String>();
??
通過上述程序示例我們可以看出,筆者定義了一個泛型類型為String的List集合。這樣一來List集合的泛型參數將會被定義為String類型。但是你有沒有想過,使用里氏替換原則或者實例化泛型類型時,其實現可以簡化泛型類型聲明嗎?答案是肯定的,在Java7.x中,允許使用運算符“<>”來做類型推斷。也就是說你只需要在聲明時標注泛型類型,實現時 無需重復 標注。
使用“<>”類型推斷運算符簡化泛型語法:
List<String> list = new ArrayList<>();
??
三、字面值下劃線支持
不知道大家有沒有過同筆者一樣的煩惱,早在Java7.x版本之前,咱們在定義int或者long類型等變量的字面值時,往往會因為其定義的 值過長 ,從而嚴重影響后續的 可讀性 。如果你也是這么覺得,那么你可以考慮使用Java7.x為字面值操作提供的可讀性優化。那便是允許你直接的字面值中使用符號“_”進行 切分 ,這樣一來不僅可以提升可讀性,還能夠清晰的分辨出字面值的長度。當然程序運行時自然會將“_”符號進行提取再做運算。
使用“_”符號進行字面值可讀性優化:
int money = 100_000_000;
??
四、switch字面值支持
Java一共為開發人員提供了2種多路分支語句,一種是大家常用的if-else,另一種則是switch語句。早在Java7.x版本之前, switch 語句表達式值只能定義 byte 、 short 、 int 和 char等 4 種 類型,且該語句表達式值 只能 匹配一個 ,故不能重復。但是Java7.x的到來允許switch定義另一種 全新 的表達式值,那就是String類型。
使用String類型作為Switch表達式值:
switch("a") { case "a": System.out.println("a"); break; case "b": System.out.println("b"); }
?
五、聲明二進制字面值
?
Java
與
C
語言、
C++
語言直接相關。
Java
語言繼承了
C
語言的語法結構,而
OMT(Object Modeling Technique
,對象模型)則是直接從
C++
語言改編而來的。所以早在
Java7.x
版本之前,開發人員只能夠定義十進制、八進制、十六進制等字面值。但是現在你完全可以使用“
0b
”字符為
前綴
定義二進制字面值。
定義二進制字面值:
int test = 0b010101;
?
當然這里筆者需要提示你的是,雖然咱們可以直接在程序中定義二進制字面值。但是在程序運算時,仍然會將其 轉換 成十進制展開運算和輸出。
?
六、catch表達式調整
談到catch語句的時候,不得不提到try語句,因為它們彼此之間存在 相互依賴、相互關聯 的關系。在Java程序中捕獲一個異常采用的是try和catch語句,try語句里面所包含的代碼塊都是需要進行 異常監測 的,而catch語句里面所包含的代碼塊,則是告訴程序當異常發生的時候所需要執行的 異常處理 。
談到捕獲異常,在Java7.x之前有2種方式。第一種是采用定義多個catch代碼塊,另外一種則是直接使用Exception(可恢復性異常超類)進行捕獲。但是現在,如果你覺得不想 籠統 的將所有異常定義為Exception進行捕獲,或者 糾結 于反復定義catch代碼塊,那么你完全可以采用Java7.x的catch表達式調整。Java7.x允許你在catch表達式內部使用“|”運算符匹配多個異常類型,當觸發異常時,異常類型將自動進行 類型匹配 操作。
使用“|”運算符定義catch表達式:
try { //... } catch (SQLException | Exception e) { e.printStackTrace(); }
?
七、文件系統改變
既然本章節咱們已經談到了Java的文件系統(FileSystem),那么必然 同樣 也會關聯到I/O技術。其實 所謂 I/O(Input/Outp ut) 指的就是數據輸入 / 輸出的 過程 ,我們稱之為流( 數據通信通道 )這個概念。 比如當 Java 應用程序需要讀取目標數據源的數據時,則開啟輸入流。需要寫入時,則開啟輸出流。數據源允許是本地磁盤、內存或者是網絡中的數據。
向目標數據源讀取數據:
?
向目標數據源寫入數據:
Java的文件系統主要由java.io及java.nio兩個包內的組件 構成 。 早在Java7.x之前,文件的操作一向都比較 棘手 。當然筆者這里提出的棘手,更多的是指向Java API對文件的管理的 不便 。比如咱們需要編寫一個程序,這個程序的功能僅僅只是拷貝文件后進行粘貼。但就是連這樣簡單的程序邏輯實現,開發人員動則都需要編寫幾十行 有效代碼 。
使用Java File API操作文件核心示例:
/* 復制目標數據源數據 */ BufferedInputStream reader = new BufferedInputStream( new FileInputStream(COPYFILEPATH)); byte[] content = new byte[reader.available()]; reader.read(content); /* 將復制數據粘貼至新目錄 */ BufferedOutputStream write = new BufferedOutputStream( new FileOutputStream(PASTEFILEPATH)); write.write(content);
?
通過上述程序示例我們可以看出,僅僅只是編寫一個簡單的文件復制粘貼邏輯,我們的代碼量都大得 驚人 。如果你也認同上述程序的 繁瑣 ,那么你完全有必要體驗下Java7.x對文件系統的一次全新 改變 。
Java7.x推出了全新的NIO.2 API以此改變針對文件管理的不便,使得在java.nio.file包下使用 Path、Paths、 Files、 WatchService、 FileSystem 等常用類型可以很好的 簡化 開發人員對文件管理的編碼工作。
咱們就先從Path接口開始進行講解吧。Path接口的 某些功能 其實可以和java.io包下的File類型 等價 ,當然這些功能僅限于 只讀操作 。在實際開發過程中,開發人員可以聯用Path接口和Paths類型,從而獲取文件的一系列上下文信息。
Path接口常用方法如下:
方法名稱 | 方法返回類型 | 方法描述 |
getNameCount() | int | 獲取當前文件節點數 |
getFileName() | java.nio.file.Path | 獲取當前文件名稱 |
getRoot() | java.nio.file.Path | 獲取當前文件根目錄 |
getParent() | java.nio.file.Path | 獲取當前文件上級關聯目錄 |
?
聯用Path接口和Paths類型獲取文件信息:
@Test public void testFile() { Path path = Paths.get("路徑:/文件"); System.out.println("文件節點數:" + path.getNameCount()); System.out.println("文件名稱:" + path.getFileName()); System.out.println("文件根目錄:" + path.getRoot()); System.out.println("文件上級關聯目錄:" + path.getParent()); }
?
通過上述程序示例我們可以看出,聯用Path接口和Paths類型可以很方便的訪問到目標文件的上下文信息。當然這些操作全都是只讀的,如果開發人員想對文件進行其它 非只讀 操作,比如文件的創建、修改、刪除等操作,則可以使用Files類型進行操作。
Files類型常用方法如下:
方法名稱 | 方法返回類型 | 方法描述 |
createFile() | java.nio.file.Path | 在指定的目標目錄創建新文件 |
delete() | void | 刪除指定目標路徑的文件或文件夾 |
copy() | java.nio.file.Path | 將指定目標路徑的文件拷貝到另一個文件中 |
move() | java.nio.file.Path | 將指定目標路徑的文件轉移到其他路徑下,并刪除源文件 |
?
使用Files類型復制、粘貼文件示例:
Files.copy(Paths.get("路徑:/源文件"), Paths.get("路徑:/新文件"));
?
通過上述程序示例我們可以看出,使用Files類型來管理文件,相對于傳統的I/O方式來說更加 方便 和 簡單 。因為 具體的操作實現將全部移交給NIO.2 API,開發人員則無需關注。
Java7.x還為開發人員提供了一套 全新 的文件系統功能,那就是文件監測。在此或許有很多朋友并不知曉文件監測有何意義及目,那么請大家回想下調試成 熱發布 功能 后的Web容器。當項目迭代后并重新部署時,開發人員無需對其進行手動重啟,因為Web容器一旦監測到文件發生改變后,便會自動去 適應 這些“變化”并重新進行內部 裝載 。Web容器的熱發布功能同樣也是基于文件監測功能,所以不得不承認,文件監測功能的出現對于Java文件系統來說是具有 重大意義 的。
?
提示 :
就事論事而言,Java7.x的文件監測功能多少存在一些性能和功能上的 缺陷 。但隨著Java后續版本的迭代,筆者相信會有那么一天,足以讓某些整天在論壇上打口水戰的“高手”們閉嘴。
?
如果在程序中需要使用Java7.x的文件監測功能,那么我們務必需要了解 java.nio.file包下的 WatchService接口。 WatchService接口不僅 作為監測服務,還管理著具體的 監控細節 。
我們可以通過使用 java.nio.file包下的FileSystems類型,并調用FileSystems類型的newWatchService()方法,從而獲取到 WatchService接口的對象實例。
獲取 WatchService接口實例:
WatchService watchService = FileSystems.getDefault() .newWatchService();
?
文件監測是基于 事 件驅動 的,事件觸發是作為監測的 先決條件 。開發人員可以使用java.nio.file包下的StandardWatchEventKinds類型提供的3種字面常量來定義監測事件類型,值得注意的是監測事件需要和 WatchService實例一起進行 注冊 。
StandardWatchEventKinds類型提供的監測事件:
1、 ENTRY_CREATE:文件或文件夾新建事件 ;
2、 ENTRY_DELETE:文件或文件夾刪除事件 ;
3、 ENTRY_MODIFY:文件或文件夾粘貼事件 ;
?
使用 WatchService類型實現文件監控完整示例:@Test public void testWatch() { /* 監控目標路徑 */ Path path = Paths.get("C:/"); try { /* 創建文件監控對象 */ WatchService watchService = FileSystems.getDefault() .newWatchService(); /* 注冊文件監控的所有事件類型 */ path.register(watchService, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); /* 循環監測文件 */ while (true) { WatchKey watchKey = watchService.take(); /* 迭代觸發事件的所有文件 */ for (WatchEvent<?> event : watchKey.pollEvents()) System.out.println(event.context().toString() + " 事件類型:" + event.kind()); if (!watchKey.reset()) return; } } catch (Exception e) { e.printStackTrace(); } }
??
通過上述程序示例我們可以看出,使用 WatchService接口 進行文件監控非常簡單和方便。首先我們需要定義好目標監控路徑,然后 調用 FileSystems 類型的newWatchService()方法 創建WatchService對象。接下來我們還需使用Path接口的register()方法注冊WatchService實例及監控事件。當這些基礎作業層全部準備好后,我們再編寫外圍 實時監測 循環。最后迭代WatchKey來獲取所有 觸發 監控事件的文件即可。
?
提示 :
如果在項目中使用上述程序示例,筆者建議你最好將這段監控代碼進行 異步化 。因為死循環會占用主線程,后續代碼將永遠得不到執行機會。
?
八、探討Java I/O模型
在基于分布式的編程環境中,系統性能的 瓶頸 往往由I/O讀寫性決定。這是不可否認的事實,也是眾多開發人員首要考慮的優化問題。如果在Windows環境下我們使用阻塞I/O模型來編寫分布式應用,其維護成本的往往超出你的想象。因為客戶端的 鏈接數量直接決定了服務器內存開辟的線程數量 * 2 (包含:接受線程、輸出線程),并且這些線程是無法采取線程池優化的,因為線程的執行之間 大于 其創建和銷毀時間。長時間的大量并發線程掛起,不僅CPU要做實時 任務切換 ,其整體物理資源都將一步步被 蠶食 ,直至最后程序崩潰。 在早期的網絡編程中,采取阻塞I/O模型來編寫分布式應用,唯一能做性能優化只有采取傳統的 硬件式堆機 。在付出高昂的硬件成本開銷時,其項目的維護性也令開發人員頭痛。而且在實際的開發過程中,大部分開發人員會選擇將項目部署在Linux下運行。跟Windows 內核結構 不同的是,Linux環境下是沒有真正意義上的線程概念。其所謂的線程都是采用 進程模擬 的方式,也就是 偽線程 。筆者希望大家能夠明白,對于并發要求極高的分布式應用,一旦采用阻塞IO模型編寫就等于自尋死路。
Java的I/O模型由同步I/O和異步I/O構成。同步I/O模型包含:阻塞I/O和非阻塞I/O,而在Windows環境下只要調用了IOCP的I/O模型,就是真正意義上的異步I/O。
Java的I/O模型示例圖:
?
IOCP(Input/Outut Completion Port,輸入/輸出完成端口)簡單來說是一種 系統級 的 高性能 異步I/O模型。應用程序中所有的I/O操作將全部 委托 給操作系統線程去執行,直至最后通知并返回結果。Java7.x對IOCP進行了 深度封裝 ,這使得開發人員可以使用IOCP API編寫高效的分布式應用。當然IOCP 僅限 于使用在Windows平臺,因而無法在Linux平臺上使用它(Linux平臺上可以通過Epoll模擬IOCP實現)。
?
提示 :
有過網絡編程經驗的開發人員都應該明白,在Windows平臺下性能最好的I/O模型是IOCP,Linux平臺下則是EPOLL。但是EPOLL并不算真正意義上的異步I/O,EPOLL只是在盡可能的 模擬 IOCP而已。因為按照Unix網絡編程的劃分,多路復用I/O仍然屬于同步I/O模型,也就是說EPOLL其實是屬于多路復用I/O。
簡單來說異步I/O的特征必須滿足如下2點:
1、I/O請求與I/O操作不會阻塞;
2、并非程序自身完成I/O操作,由操作系統線程處理實際的I/O操作,直至最后通知并返回結果;
?
早在Java4.x的時候,NIO(Java New Input/Output,Java新輸入/輸出)的出現,使得開發人員可以徹底從阻塞I/O的 噩夢 中掙脫出來。但編寫NIO的成本較大,學習難度也比較高,使得諸多開發人員望而卻步(目前比較成熟的NIO Frameworks有:Mina、 Netty )。但理解非阻塞I/O的原理還是非常有必要,先來觀察下述采用阻塞I/O模式編寫的分布式應用示例:
@Test public void testServer() { try { ServerSocket server = new ServerSocket(8888); Socket clist = server.accept(); BufferedReader reader = new BufferedReader(new InputStreamReader( clist.getInputStream())); /* 未收到I/O請求時阻塞 */ System.out.println(reader.readLine()); } catch (Exception e) { e.printStackTrace(); } }
??
I/O的工作內容我們可以根據其 性質 劃分為2部分:I/O請求和I/O操作。上述程序示例我們采用的是阻塞I/O模型,可以很明確的發現當客戶端成功握手服務端后,如果服務端并沒有收到客戶端的I/O請求,服務端會在reader.readLine()方法處阻塞。直到成功接收到I/O請求后,服務端才會開始執行實際的I/O操作。運用阻塞I/O模式進行分布式編程,為了保證服務端與客戶端集合的成功會話,我們不得不為每一條客戶端連接都開辟獨立的線程執行I/O操作。當然在實際的開發過程中,或許已經沒有開發人員會做這么 荒唐 的事情了。
非阻塞I/O和阻塞I/O最大的不同在于,非阻塞I/O并不會在I/O請求時產生阻塞。也就是說如果服務端沒有收到I/O請求時,非阻塞I/O會 “ 持續輪循 ” I/O請求,當有請求進來后就開始執行I/O操作并 阻塞請求進程 。Java7.x允許開發人員使用IOCP API進行異步I/O編程,這使得開發人員不必再關心I/O 是否阻塞 。因為應用程序中所有的I/O操作將全部 委托 給操作系統線程去執行,直至最后通知并返回結果。
?
九、Swing Framework(JSR 296規范)支持
筆者其實對Swing 非常厭惡 ,如果可以的話筆者希望Oracle能夠 廢除 掉Swing這項技術。早在08年的時候筆者由于項目需要,曾飽受Swing的折磨。 繁瑣的布局、組件加載優化、冗長代碼維護 等 這些令人痛苦和發指的問題,筆者相信使用過Swing的人開發人員都能發出相同的感嘆。
早期的Java GUI(圖形用戶界面)主要由AWT技術主導,但隨著用戶對 胖客戶端 技術的豐富度要求逐漸提高,AWT主鍵逐漸被Swing替代。Swing其實繼承于AWT,并提供有更加絢麗的視圖組件效果。何況相對于 重量級 的AWT組件來說,Swing顯得更加 輕量 。
筆者剛才說過,Swing雖然相對于AWT來說組件內容更加豐富,但仍然掩蓋不了其 繁瑣 的操作實現。如果對組件性能有過高要求,或者需要實現快速開發,筆者更建議你使用SWT或者JFace技術( 無需指望使用IDE工具進行可視化編程,因為這純粹是吃力不討好 )。因為這2種技術可以看成是Swing的過渡,且相對Swing來說性能和豐富度更加優秀。
既然Java7.x對Swing仍不忘眷顧優化,那希望大家還是支持一下吧。從官方聲明可以看出,JSR 296規范的目標是簡化Swing的開發難度,且提供有更加豐富的組件資源。如果對于從未接觸過Swing編程的開發人員,筆者倒是建議你嘗試一下,或許你并不反感。
?
十、JVM內核升級之Class Loader架構調整
類裝載器(Class Loader)屬于JVM體系結構的重要
組成部分
,它是將Java類型裝載進JVM內部的
關鍵一環
。它使得Java類型可以動態的被裝載到JVM內部解釋并運行。
在JVM內部存在著2種類型的類裝載器:非自定義類裝載器和自定義類裝載器 。非自定義類裝載器負責裝載Java API中的類型及Java程序中的類型,而自定義類裝載器能夠使用自定義的方式來裝載其類型。不同類型的類裝載器所裝載的類型將被存放于JVM內部不同的
命名空間
中。
非自定義類裝載器由JVM內部3個核心類裝載器構成:
1、BootStrap ClassLoader;
2、ExtClassLoader;
3、AppClassLoader;
?
BootStrap ClassLoader也稱為 啟動類裝載器 ,它是JVM內部最 頂層 的類裝載器。BootStrap ClassLoader主要負責裝載核心Java API中的類型。ExtClassLoader負責裝載擴展目錄下的類型。AppClassLoader則負責裝載ClassPath(Java應用類路徑)下指定的所有類型。其中ExtClassLoader和AppClassLoader都屬于BootStrap ClassLoader的 派生 類裝載器。
在Object內部封裝著一個通過JNI(Java Native Interface,Java本地接口)方式調用的getClass()本地方法,該方法返回一個Class類型。對于開發人員而言,允許直接調用其getClassLoader()方法獲取類裝載器實例。
使用getClassLoader()方法獲取類裝載器:
@Test public void testClassLoader() throws Exception { /* BootStrap ClassLoader裝載Java API中的類型 */ ClassLoader loader = System.class.getClassLoader(); System.out.println(null != loader ? loader.getClass().getName() : loader); /* ExtClassLoader裝載擴展目錄下的類型 */ System.out.println(CollationData_ar.class.getClassLoader().getClass() .getName()); /* AppClassLoader裝載ClassPath下指定的所有類型 */ System.out.println(this.getClass().getClassLoader().getClass() .getName()); }
?
通過上述程序示例我們可以看出,System類型是被BootStrap ClassLoader所裝載的。但程序的輸出結果卻是Null,當然這并不代表BootStrap ClassLoader不存在。因為BootStrap ClassLoader
并
不是采用Java語言編寫
,而是由C++語言編寫并
嵌入
在JVM內部,所以開發人員無法獲取其實例。CollationData_ar類型屬于jre\lib\ext目錄下的派生類,由ExtClassLoader裝載。當前類則由AppClassLoader負責裝載。
在此筆者要提示大家,ExtClassLoader和AppClassLoader都是采用Java語言編寫。所以ExtClassLoader和AppClassLoader
本身也都是Java類型
,都會被最頂層的類裝載器BootStrap ClassLoader裝載,最后才會裝載各自管轄范圍內的類型。
談到ClassLoader的架構,我們不得不提及
雙親委派模型
。在JVM內部,類裝載器裝載類型所采用的便是雙親委派模型機制。比如AppClassLoader需要將一個類型裝載進JVM內部,首先其自身并不會立即裝載,而是將目標類型
委派
給上一級,也就是ExtClassLoader。ExtClassLoader接著再繼續委派給BootStrap ClassLoader。在JVM內部最頂層的類裝載器就是BootStrap ClassLoader,首先由它負責裝載目標類型及其關聯或依賴的所有類型。如果BootStrap ClassLoader裝載失敗,則退回給ExtClassLoader裝載。如果ExtClassLoader也無法裝載,最后只能退回給AppClassLoader繼續裝載。最后當AppClassLoader都無法裝載的時候,便會拋出ClassNotFoundException異常(
開發人員可以在捕獲ClassNotFoundException異常的時候重寫ClassLoder類型的findClass()方法實現自定義類型裝載
)。
類裝載器架構示例:
?
類裝載器除了需要負責類型的裝載,還需要負責驗證目標類型的正確性、屬性內存分配、解析符號引用等操作。JVM通過裝載、連接和初始化一個Java類型,使其可以被運行時的Java應用程序所使用。其中裝載就是把二進制形式的Java類型 寫入 進 JVM內部。連接則是把已經寫入進JVM中的二進制形式的類型 合并 到JVM的運行時狀態中去。然而連接階段又分成了3個步驟:驗證、準備和解析。“驗證”步驟確保了Java類型的數據格式,“準備”步驟則負責為目標類型分配所需的內存空間,“解析”步驟負責把常量池中的符號引用轉換為直接使用。“驗證”和“解析”這2個步驟都是為最后的初始化工作做準備。
類型生命周期示例:
?
Java7.x在上述ClassLoader架構的基礎之上,進行了一些細微 調整 。在早期開發人員如果想要實現自定義類裝載器,恐怕只能實現ClassLoader類型并重寫其findClass()方法。但由于findClass()方法是按照 串行 結構 的方式執行, 或許是出于對性能和安全的考慮 。Java7.x提供了一個擁有并行執行能力的增強實現,這樣一來自定義類裝載器便可以通過 異步 方式對類型進行裝載。
?
提示 :
關于自定義類裝載器本章筆者將不再繼續講解,如果有興趣的朋友可以以郵件的形式告知筆者,筆者會為你提供幫助。
?
本章內容到此結束,由于時間倉庫,本文或許有很多不盡人意的地方,希望各位能夠理解和體諒。關于下一章的內容,筆者打算繼續講解SSJ的相關內容。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
