JAVA 虛擬機深刻研究(一)——關於Java的一些歷史

      

內容目錄:html

JAVA 虛擬機深刻研究(一)——關於Java的一些歷史java

 

JAVA 虛擬機深刻研究(二)——JVM虛擬機發展以及一些Java的新東西程序員

 

JAVA 虛擬機深刻研究(三)——Java內存區域web

 

 

 

    有本書叫作《深刻Java 虛擬機》周志明寫的,最近買來準備研讀一下,而後從今天開始不按期的寫一些讀這本書以後的一些感覺和學習記錄。今天這就是第一篇。正則表達式

        從廣義上說,Java的技術體系包含了全部運行於Java虛擬機上的語言都算是Java的技術體系內的一員,好比Clojure,JRuby,Groovy等都算是廣義的Java體系內一員。可是若是按照傳統的Java的體系Sun當年官方的體系包括:算法

1.Java程序設計語言spring

2.各類硬件平臺上的Java虛擬機編程

3.Class文件格式緩存

4.Java API類庫安全

5.來自商業機構的以及來自開源社區的第三方Java類庫。

        而後就要說到必須說的一個東西,那就是JDk,JDK包括了幾個東西,第一是Java程序設計語言,Java虛擬機,Java API 類庫這三部分統稱JDK,這個東西是咱們開發Java的最小環境。而後說說Java API類庫,它的一個子集Java SE API 子集和Java的虛擬機部分也被稱爲JRE,這個是程序運行的標準環境。我給你們貼一個圖在這,這部分就算是說完了。

Java的發展歷史沒啥可說的,我只是把我以爲很重要的一些點提出來。

       1997年2月19日,JDK發了1.1版本,這個時候出現了幾個關鍵的東西好比JDBC。在這個版本中必須提一提的是(具體的一些關鍵點有一些會在之後再講):JAR文件格式,JDBC,JavaBean,RMI,內部類,反射。

        1998年12月4日,JDK一個里程碑版本1.2,這個版本表明性技術:EJB、Java Plug-in、Java IDL,Swing,第一次內置了JIT編譯器,添加了關鍵字strictfp(用於聲明精確浮點數,被這個聲明後表示嚴格遵照FP-strict)。

        2002年2月13日,JDK發佈了1.4,添加了正則表達式,異常鏈,NIO,日誌類,XML解析器和XSLT轉換器。

        2004年9月30日,JDK的經典版本1.5,比較經典的東西,例如自動裝箱,泛型,動態註解,枚舉,可變長參數,遍歷循環(foreach).另外這個版本改進了Java的內存模型(JMM)、提供了java.util.concurrent併發包。

        後續的幾個版本我就不寫了,相信你們都是瞭解的。在Java這麼多版本中,我記錄下如下關鍵詞,後面會單獨的講講。

1.RMI(遠程調用)

2.JIT編譯器

3.NIO(非阻塞調用)

4.異常鏈

5.動態註解

6.Lambda表達式

7.Jigsaw

8.動態語言支持

9.G1垃圾回收器

10.Coin(語言細節化)

 

=============分割線=================================

後面的關於上面提到的關鍵詞,都會在這下面更新,我會逐步的查找而後把這些關鍵詞解釋清楚。這些東西有的是經過鏈接給出了一些博客或者其餘人的解釋,願意看就看看,不看也沒影響。

 

1RMI (遠程接口調用)

  關於這個東西,一百度一大堆,我就整理下吧。http://www.blogjava.net/zhenyu33154/articles/320245.html  這是一個博客,講解了RMI這個東西。

  關於遠程調用,這裏轉載一個博客來自http://blog.sina.com.cn/s/blog_56fd58ab0100mrl6.html

-------------------------------------------------------轉載---------------------------------------------------------------------------------------------------  

  在分佈式服務框架中,一個最基礎的問題就是遠程服務是怎麼通信的,在Java領域中有不少可實現遠程通信 的技術,例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,這些名詞之間究竟是些什麼關係呢,它們背後究竟是 基於什麼原理實現的呢,瞭解這些是實現分佈式服務框架的基礎知識,而若是在性能上有高的要求的話,那深刻了解這些技術背後的機制就是必須的了,在這篇 blog中咱們未來一探究竟,拋磚引玉,歡迎你們提供更多的實現遠程通信的技術和原理的介紹。

 

基本原理
要實現網絡機器間的通信,首先得來看看計算機系統網絡通訊的基本原理,在底層層面去看,網絡通訊須要作的就是將流從一臺計算機傳輸 到另一臺計算機,基於傳輸協議和網 絡IO來實現,其中傳輸協議比較 出名的有http、tcp、udp等等,http、tcp、udp都是在基於Socket概念上爲某類應用場景而擴展出的傳輸協議,網絡IO,主要有bio、nio、aio三種方式,全部的分佈式應用通信都基於這個原理而實現,只是爲了 應用的易用,各類語言一般都會提供一些更爲貼近應用易用的應用層協議。

 

應用級協議
遠程服務通信,須要達到的目標是在一臺計算機發起請求,另一臺機器在接收到請求後進行相應的處理並將結果返回給請求端,這其中 又會有諸如one way request、同步請求、異步請求等等請求方式,按照網絡通訊原理,須要實現這個須要作的就是將請求轉換成流,經過傳輸協議傳輸至遠端,遠端計算機在接 收到請求的流後進行處理,處理完畢後將結果轉化爲流,並經過傳輸協議返回給調用端。
原理是這樣的,但爲了應用的方便,業界推出了不少基於此原理之 上的應用級的協議,使得你們能夠不用去直接操做這麼底層的東西,一般應用級的遠程通訊協議會提供:
一、爲了不直接作流操做這麼麻煩,提供一種更 加易用或貼合語言的標準傳輸格式;
二、網絡通訊機制的實現,就是替你完成了將傳輸格式轉化爲流,經過某種傳輸協議傳輸至遠端計算機,遠端計算機在 接收到流後轉化爲傳輸格式,並進行存儲或以某種方式通知遠端計算機。
所 以在學習應用級的遠程通訊協議時,咱們能夠帶着這幾個問題進行學習:
一、傳輸的標準格式是什麼?
二、怎麼樣將請求轉化爲傳輸的流?
三、 怎麼接收和處理流?
四、傳輸協議是?
不過應用級的遠程通訊協議並不會在傳輸協議上作什麼多大的改進,主要是在流操做方面,讓應用層生成流 和處理流的這個過程更加的貼合所使用的語言或標準,至於傳輸協議則一般都是可選的,在java領域中知名的有:RMI、XML-RPC、Binary- RPC、SOAP、CORBA、JMS,來具體的看看這些遠程通訊的應用級協議:
--------------------------------------------------------------------------------------------------------------------------------------------------
RMI
RMI 是個典型的爲java定製的遠程通訊協議,咱們都知道,在single vm中,咱們能夠經過直接調用java object instance來實現通訊,那麼在遠程通訊時,若是也能按照這種方式固然是最好了,這種遠程通訊的機制成爲RPC(Remote Procedure Call),RMI正是朝着這個目標而誕生的。
來看下基於RMI的一次完整的遠程通訊過程的原理:
一、客戶端發起請求,請求轉交至RMI 客戶端的stub類;
二、stub類將請求的接口、方法、參數等信息進行序列化;
三、基於socket將序列化後的流傳輸至服務器端;
四、服務器端接收到流後轉發至相應的 skelton類;
五、skelton類將請求的信息反序列化後調用實際的處理類;
六、處理類處理完畢後將結果返回給skelton類;
七、 Skelton類將結果序列化,經過socket將流傳送給客戶端的stub;
八、stub在接收到流後反序列化,將反序列化後的Java Object返回給調用者。
來看jboss-remoting對於此過程的一個更好的圖示:

 

根據原理來回答下以前學習應用級協議帶着的幾個問題:
一、傳輸的標準格式是什麼?
是Java ObjectStream。
二、怎麼樣將請求轉化爲傳輸的流?
基於Java串行化機制將請求的java object信息轉化爲流。
三、怎麼接收和處理流?
根據採用的協議啓動相應的監聽端口,當有流進入後基於Java串行化機制將流進行反序列化,並根據RMI協議獲取到相應的處理對象信息,進行調用並處理, 處理完畢後的結果一樣基於java串行化機制進行返回。
四、傳輸協議是?
Socket。
--------------------------------------------------------------------------------------------------------------------------------------------------
XML-RPC
XML- RPC也是一種和RMI相似的遠程調用的協議,它和RMI的不一樣之處在於它以標準的xml格式來定義請求的信息(請求的對象、方法、參數等),這樣的好處 是什麼呢,就是在跨語言通信的時候也可使用。
來看下XML-RPC協議的一次遠程通訊過程:
一、客戶端發起請求,按照XML-RPC協 議將請求信息進行填充;
二、填充完畢後將xml轉化爲流,經過傳輸協議進行傳輸;
三、接收到在接收到流後轉換爲xml,按照XML- RPC協議獲取請求的信息並進行處理;
四、處理完畢後將結果按照XML-RPC協議寫入xml中並返回。
圖示以上過程:

Hessian <wbr>原理分析

一樣來回答問題:
一、傳輸的標準格式是?
標準格式的XML。
二、怎麼樣將請求轉化爲傳輸的流?
將XML轉化爲流。
三、怎麼接收和處理流?
經過監聽的端口獲取到請求的流,轉化爲XML,並根據協議獲取請求的信息,進行處理並將結果寫入XML中返回。
四、傳輸協議是?
Http。

--------------------------------------------------------------------------------------------------------------------------------------------------
Binary-RPC
Binary- RPC看名字就知道和XML-RPC是差很少的了,不一樣之處僅在於傳輸的標準格式由XML轉爲了二進制的格式。
一樣來回答問題:
一、傳輸 的標準格式是?
標準格式的二進制文件。
二、怎麼樣將請求轉化爲傳輸的流?
將二進制格式文件轉化爲流。
三、 怎麼接收和處理流?
經過監聽的端口獲取到請求的流,轉化爲二進制文件,根據協議獲取請求的信息,進行處理並將結果寫入XML中返回。
四、 傳輸協議是?
Http。
--------------------------------------------------------------------------------------------------------------------------------------------------
SOAP
SOAP 原意爲Simple Object Access Protocol,是一個用於分佈式環境的、輕量級的、基於XML進行信息交換的通訊協議,能夠認爲SOAP是XML RPC的高級版,二者的原理徹底相同,都是http+XML,不一樣的僅在於二者定義的XML規範不一樣,SOAP也是Webservice採用的服務調用協 議標準,所以在此就很少加闡述了。
--------------------------------------------------------------------------------------------------------------------------------------------------
CORBA
Common Object Request Broker Architecture(公用對象請求代理[調度]程序體系結構),是一組用來定義「分佈式對象系統」的標準,由OMG(Object Menagement Group)做爲發起和標準制定單位。CORBA的目的是定義一套協議,符合這個協議的對象能夠互相交互,不論它們是用什麼樣的語言寫的,不論它們運行於 什麼樣的機器和操做系統。
CORBA在我看來是個相似於SOA的體系架構,涵蓋可選的遠程通訊協議,但其自己不能列入通訊協議這裏來說,並且 CORBA基本淘汰,再加上對CORBA也不怎麼懂,在此就不進行闡述了。
--------------------------------------------------------------------------------------------------------------------------------------------------
JMS
JMS 呢,是實現java領域遠程通訊的一種手段和方法,基於JMS實現遠程通訊時和RPC是不一樣的,雖然能夠作到RPC的效果,但由於不是從協議級別定義的, 所以咱們不認爲JMS是個RPC協議,但它確實是個遠程通訊協議,在其餘的語言體系中也存在着相似JMS的東西,能夠統一的將這類機制稱爲消息機制,而消 息機制呢,一般是高併發、分佈式領域推薦的一種通訊機制,這裏的主要一個問題是容錯(詳細見ErLang論文)。
來看JMS中的一次遠程通訊的過 程:
一、客戶端將請求轉化爲符合JMS規定的Message;
二、經過JMS API將Message放入JMS Queue或Topic中;
三、如爲JMS Queue,則發送中相應的目標Queue中,如爲Topic,則發送給訂閱了此Topic的JMS Queue。
四、處理端則經過輪訓JMS Queue,來獲取消息,接收到消息後根據JMS協議來解析Message並處理。
回答問 題:
一、傳輸的標準格式是?
JMS規定的Message。
二、怎麼樣將請求轉化爲傳輸的流?
將參數信息放入Message中便可。
三、怎麼接收和處理流?
輪訓JMS Queue來接收Message,接收到後進行處理,處理完畢後仍然是以Message的方式放入Queue中發送或Multicast。
四、傳 輸協議是?
不限。
基於JMS也是經常使用的實現遠程異步調用的方法之一。

可選實現技術
固然,在上面的原理中並無介紹到全部的java領域可選的遠程通訊協議了,例如還有EJB採用的ORMI、Spring本身 定義的一個簡單的Http Invoker等等。
看完原理後咱們再來看看目前java領域可用於實現遠程通信的框架或library,知名的 有:JBoss-Remoting、Spring-Remoting、Hessian、Burlap、XFire(Axis)、ActiveMQ、 Mina、Mule、EJB3等等,來對每種作個簡單的介紹和評價,其實呢,要作分佈式服務框架,這些東西都是要有很是深入的瞭解的,由於分佈式服務框架 實際上是包含了解決分佈式領域以及應用層面領域兩方面問題的。
固然,你也能夠本身根據遠程網絡通訊原理(transport protocol+Net IO)去實現本身的通信框架或library。
那麼在瞭解這些遠程通信的框架或library時,會帶着什麼問題去學 習呢?
一、是基於什麼協議實現的?
二、怎麼發起請求?
三、怎麼將請求轉化爲符合協議的格式的?
四、使用什麼傳輸協議傳 輸?
五、響應端基於什麼機制來接收請求?
六、怎麼將流還原爲傳輸格式的?
七、處理完畢後怎麼迴應?
--------------------------------------------------------------------------------------------------------------------------------------------------
JBoss-Remoting
Jboss- remoting是由jboss編寫的一個java領域的遠程通信框架,基於此框架,能夠很簡單的實現基於多種傳輸協議的java對象的RPC。
直 接來回答問題:
一、是基於什麼協議實現的?
JBoss-Remoting是個通信框架,所以它支持多種協議方式的通訊,例如純粹的socket+io方式、rmi方式、http+io方式等。
二、 怎麼發起請求?
在JBoss-Remoting中,只需將須要發起的請求參數對象傳入jboss-remoting的InvocationRequest對象便可,也可 根據協議基於InvocationRequest封裝符合需求的InvocationRequest對象。
三、怎麼將請求轉化爲符合協議的格式 的?
JBoss-Remoting基於Java串行化機制或JBoss本身的串行化實現來將請求轉化爲對象字節流。
四、使用 什麼傳輸協議傳輸?
支持多種傳輸協議,例如socket、http等。
五、響應端基於什麼機制來接收請求?
響應端只需將本身的處理對象註冊到JBoss-Remoting提供的server端的Connector對象中便可。
六、怎麼將流還原爲傳輸 格式的?
JBoss-Remoting基於java串行化機制或jboss本身的串行化實現來將請求信息還原爲java對象。
七、 處理完畢後怎麼迴應?
處理完畢後將結果對象直接返回便可,jboss-remoting會將此對象按照協議進行序列化,返回至調用端。
另外,jboss- remoting支持多種通訊方式,例如同步/異步/單向通訊等。

 

--------------------------------------------------------------------------------------------------------------------------------------------------
Spring-Remoting
Spring- remoting是Spring提供java領域的遠程通信框架,基於此框架,一樣也能夠很簡單的將普通的spring bean以某種遠程協議的方式來發布,一樣也能夠配置spring bean爲遠程調用的bean。
一、是基於什麼協議實現的?
和JBoss-Remoting同樣,做爲一個遠程通信的框架,Spring經過集成多種遠程通信的library,從而實現了對多種協議的支持,例如 rmi、http+io、xml-rpc、binary-rpc等。
二、怎麼發起請求?
在Spring中,因爲其對於遠程調用的bean採用的是proxy實現,發起請求徹底是經過服務接口調用的方式。
三、怎麼將請求轉化爲符合協議 的格式的?
Spring按照協議方式將請求的對象信息轉化爲流,例如Spring Http Invoker是基於Spring本身定義的一個協議來實現的,傳輸協議上採用的爲http,請求信息是基於java串行化機制轉化爲流進行傳輸。
四、 使用什麼傳輸協議傳輸?
支持多種傳輸協議,例如rmi、http等等。
五、響應端基於什麼機制來接收請求?
響應端遵循協議方式來接收請求,對於使用者而言,則只需經過spring的配置方式將普通的spring bean配置爲響應端或者說提供服務端。
六、 怎麼將流還原爲傳輸格式的?
按照協議方式來進行還原。
七、處理完畢後怎麼迴應?
處理完畢後直接返回便可,spring-remoting將根據協議方式來作相應的序列化。

 

--------------------------------------------------------------------------------------------------------------------------------------------------
Hessian
Hessian 是由caucho提供的一個基於binary-RPC實現的遠程通信library。
一、是基於什麼協議實現的?
基於Binary-RPC協議實現。
二、怎麼發起請求?
需經過Hessian自己提供的API來發起請求。
三、怎麼 將請求轉化爲符合協議的格式的?
Hessian經過其自定義的串行化機制將請求信息進行序列化,產生二進制流。
四、使用什麼 傳輸協議傳輸?
Hessian基於Http協議進行傳輸。
五、響應端基於什麼機制來接收請求?
響應端根據Hessian提供的API來接收請求。
六、怎麼將流還原爲傳輸格式的?
Hessian根據其私有的串行化機制來將請求信息進行反序列化,傳遞給使用者時已經是相應的請求信息對象了。
七、處理完畢後怎麼迴應?
處理完畢後直接返回,hessian將結果對象進行序列化,傳輸至調用端。

 

--------------------------------------------------------------------------------------------------------------------------------------------------
Burlap
Burlap 也是有caucho提供,它和hessian的不一樣在於,它是基於XML-RPC協議的。
一、是基於什麼協議實現的?
基於XML-RPC協議實現。
二、怎麼發起請求?
根據Burlap提供的API。
三、怎麼將請求轉化爲符合協議的格 式的?
將請求信息轉化爲符合協議的XML格式,轉化爲流進行傳輸。
四、使用什麼傳輸協議傳輸?
Http協議。
五、響應端基於什麼機制來接收請求?
監聽Http請求。
六、怎麼將流還原爲傳輸格式的?
根據XML-RPC協議進行還原。
七、處理完畢後怎麼迴應?
返回結果寫入XML中,由Burlap返回至調用端。

 

--------------------------------------------------------------------------------------------------------------------------------------------------
XFire、 Axis
XFire、Axis是Webservice的實現框架,WebService可算是一個完整的SOA架構實現標準了,所以採用 XFire、Axis這些也就意味着是採用webservice方式了。
一、是基於什麼協議實現的?
基於SOAP協議。
二、 怎麼發起請求?
獲取到遠端service的proxy後直接調用。
三、怎麼將請求轉化爲符合協議的格式的?
將請求信息轉化爲遵循SOAP協議的XML格式,由框架轉化爲流進行傳輸。
四、使用什麼傳輸協議傳輸?
Http協議。
五、 響應端基於什麼機制來接收請求?
監聽Http請求。
六、怎麼將流還原爲傳輸格式的?
根據SOAP協議進行還原。
七、處理完畢後怎麼迴應?
返回結果寫入XML中,由框架返回至調用端。

 

--------------------------------------------------------------------------------------------------------------------------------------------------
ActiveMQ
ActiveMQ 是JMS的實現,基於JMS這類消息機制實現遠程通信是一種不錯的選擇,畢竟消息機制自己的功能使得基於它能夠很容易的去實現同步/異步/單向調用等,而 且消息機制從容錯角度上來講也是個不錯的選擇,這是Erlang可以作到容錯的重要基礎。
一、是基於什麼協議實現的?
基於JMS協議。
二、怎麼發起請求?
遵循JMS API發起請求。
三、怎麼將請求轉化爲符合協議的格式的?
不太清楚,猜測應該是二進制流。
四、使用什麼傳輸協議傳輸?
支持多種傳輸協議,例如socket、http等等。
五、 響應端基於什麼機制來接收請求?
監聽符合協議的端口。
六、怎麼將流還原爲傳輸格式的?
同問題3。
七、 處理完畢後怎麼迴應?
遵循JMS API生成消息,並寫入JMS Queue中。
基於JMS此類機制實現遠程通信的例子有 Spring-Intergration、Mule、Lingo等等。

 

--------------------------------------------------------------------------------------------------------------------------------------------------
Mina
Mina 是Apache提供的通信框架,在以前一直沒有提到網絡IO這塊,以前說起的框架或library基本都是基於BIO的,而Mina是採用NIO 的,NIO在併發量增加時對比BIO而言會有明顯的性能提高,而java性能的提高,與其NIO這塊與OS的緊密結合是有不小的關係的。
一、是基 於什麼協議實現的?
基於純粹的Socket+NIO。
二、怎麼發起請求?
經過Mina提供的Client API。
三、怎麼將請求轉化爲符合協議的格式的?
Mina遵循java串行化機制對請求對象進行序列化。
四、使用什麼傳輸協議傳輸?
支持多種傳輸協議,例如socket、http等等。
五、響應端基於什麼機制來接收請求?
以NIO的方式監聽協議端口。
六、 怎麼將流還原爲傳輸格式的?
遵循java串行化機制對請求對象進行反序列化。
七、處理完畢後怎麼迴應?
遵循Mina API進行返回。
MINA是NIO方式的,所以支持異步調用是毫無懸念的。

 

--------------------------------------------------------------------------------------------------------------------------------------------------
EJB
EJB 最突出的在於其分佈式,EJB採用的是ORMI協議,和RMI協議是差很少的,但EJB在分佈式通信的安全控制、transport pool、smart proxy等方面的突出使得其在分佈式領域是不可忽視的力量。
一、是基於什麼協議實現的?
基於ORMI協議。
二、怎 麼發起請求?
EJB調用。
三、怎麼將請求轉化爲符合協議的格式的?
遵循java串行化機制對請求對象進行序列化。
四、使用什麼傳輸協議傳輸?
Socket。
五、響應端基於什麼機制來 接收請求?
監聽協議端口。
六、怎麼將流還原爲傳輸格式的?
遵循java串行化機制對請求對象進行反序列化。
七、處理完畢後怎麼迴應?
直接返回處理對象便可。

 

在以前的分佈式服務框架系列的文章中對於jndi有誤導的嫌疑,在這篇blog中也順帶的提下jndi的機制,因爲JNDI取決於具體的實現,在這 裏只能是講解下jboss的jndi的實現了。
在將對象實例綁定到jboss jnp server後,當遠程端採用context.lookup()方式獲取遠程對象實例並開始調用時,jboss jndi的實現方法是從jnp server上獲取對象實例,將其序列化回本地,而後在本地進行反序列化,以後在本地進行類調用。
經過這個機制,就能夠知道了,本地實際上是必須有 綁定到jboss上的對象實例的class的,不然反序列化的時候確定就失敗了,而遠程通信須要作到的是在遠程執行某動做,並獲取到相應的結果,可見純粹 基於JNDI是沒法實現遠程通信的。
但JNDI也是實現分佈式服務框架一個很關鍵的技術點,由於能夠經過它來實現透明化的遠端和本地調用,就像 ejb,另外它也是個很好的隱藏實際部署機制(就像datasource)等的方案。

總結
由上一系列的分析可知,在遠程通信領域中,涉及的知識點仍是至關的多的,例若有:通訊協議(Socket/tcp/http/udp /rmi/xml-rpc etc.)、消息機制、網絡IO(BIO/NIO/AIO)、MultiThread、本地調用與遠程調用的透明化方案(涉及java classloader、Dynamic Proxy、Unit Test etc.)、異步與同步調用、網絡通訊處理機制(自動重連、廣播、異常、池處理等等)、Java Serialization (各類協議的私有序列化機制等)、各類框架的實現原理(傳輸格式、如何將傳輸格式轉化爲流的、如何將請求信息轉化爲傳輸格式的、如何接收流的、如何將流還 原爲傳輸格式的等等),要精通其中的哪些東西,得根據實際需求來決定了,只有在瞭解了原理的狀況下才能很容易的作出選擇,甚至能夠根據需求作私有的遠程通 訊協議,對於從事分佈式服務平臺或開發較大型的分佈式應用的人而言,我以爲至少上面說起的知識點是須要比較瞭解的。

 

--------------------------------------------轉載完成--------------------------------------------------------------------------

 

2.關於JIT編譯器(Just in time)

  編譯器是幹什麼的不用多說,C和C++這種語言,他們的編譯器叫作靜態編譯器,會把代碼直接編譯爲能夠被計算機執行的二進制代碼,PHP這種語言的「編譯器」,叫作解釋器,只須要安裝正確的解釋器,它們就能運行在任何CPU之上。當程序被執行的時候,程序代碼會被逐行解釋並執行。兩種方式各有優缺點:

 

編譯型語言的優缺點:

  速度快:由於在編譯的時候它們可以獲取到更多的有關程序結構的信息,從而有機會對它們進行優化。

  適用性差:它們編譯獲得的二進制代碼每每是CPU相關的,在須要適配多種CPU時,可能須要編譯屢次。

 

解釋型語言的優缺點:

  適應性強:只須要安裝正確的解釋器,程序在任何CPU上都可以被運行

  速度慢:由於程序須要被逐行翻譯,致使速度變慢。同時由於缺少編譯這一過程,執行代碼不能經過編譯器進行優化。

 

  Java採用了一箇中間方案,

    Java代碼靜不靜態編譯呢?編譯!被編譯成Java字節碼,而不是針對某種CPU的二進制代碼。

    Java代碼解釋執行不?固然!Java字節碼須要被java程序解釋執行,此時,Java字節碼被翻譯成CPU相關的二進制代碼。

  而JIT的做用就是在解釋的時候將字節碼編譯爲適合CPU的二進制代碼,因爲是在運行的時候編譯,因此叫作just in time。

關於JIT調優的部分,暫時很少說。有興趣能夠百度下

 

3.NIO(同步非阻塞)

  提到Javde的IO其實有這麼幾個同步阻塞的BIO、同步非阻塞的NIO、異步非阻塞的AIO

  先說BIO和NIO,他們主要的區別在於,BIO每每須要引入多線程,每一個鏈接都有一個線程,而NIO則單線程或者是少線程,多個鏈接共享線程。NIO這種機制是什麼樣的呢?首先一個鏈接建立後,不會對應一個線程,它會被註冊到多路複用器上面,當多路複用器輪詢發現有請求了,這個時候纔會去開啓一個線程處理這個請求,也就是說一個請求一個線程。

 

  在說道上面幾個關鍵詞:同步,異步,阻塞,非阻塞,不得不祭出一個很好地例子

以銀行取款爲例:

  • 同步 : 本身親自出馬持銀行卡到銀行取錢(使用同步IO時,Java本身處理IO讀寫)。

  • 異步 : 委託一小弟拿銀行卡到銀行取錢,而後給你(使用異步IO時,Java將IO讀寫委託給OS處理,須要將數據緩衝區地址和大小傳給OS(銀行卡和密碼),OS須要支持異步IO操做API)。

  • 阻塞 : ATM排隊取款,你只能等待(使用阻塞IO時,Java調用會一直阻塞到讀寫完成才返回)。

  • 非阻塞 : 櫃檯取款,取個號,而後坐在椅子上作其它事,等號廣播會通知你辦理,沒到號你就不能去,你能夠不斷問大堂經理排到了沒有,大堂經理若是說還沒到你就不能去 (使用非阻塞IO時,若是不能讀寫Java調用會立刻返回,當IO事件分發器會通知可讀寫時再繼續進行讀寫,不斷循環直到讀寫完成)。

  

  關於Java對於這三種的支持,以下

Java對BIO、NIO、AIO的支持:

  • Java BIO : 同步並阻塞,服務器實現模式爲一個鏈接一個線程,即客戶端有鏈接請求時服務器端就須要啓動一個線程進行處理,若是這個鏈接不作任何事情會形成沒必要要的線程開銷,能夠經過線程池機制改善。

  • Java NIO : 同步非阻塞,服務器實現模式爲一個請求一個線程,即客戶端發送的鏈接請求都會註冊到多路複用器上,多路複用器輪詢到鏈接有I/O請求時才啓動一個線程進行處理。

  • Java AIO(NIO.2) : 異步非阻塞,服務器實現模式爲一個有效請求一個線程,客戶端的I/O請求都是由OS先完成了再通知服務器應用去啓動線程進行處理。

 

  很顯然,BIO適用於鏈接數比較小,架構固定的應用,它的併發集中在應用內,也是1.4之前的Java惟一的選擇;NIO適用於鏈接數目多,可是鏈接比較短(好比聊天)的應用,併發也集中在應用內,1.4開始支持,而AIO則適用於鏈接數目大,操做重/長(相冊)的應用,併發充分調動了OS的併發性能,JDK7開始支持。而後說到了高性能IO就必須提到兩種模式Reactor和Proactor。咱們接着說,首先咱們先明確幾個概念:

 

  系統I/O 可分爲阻塞型, 非阻塞同步型以及非阻塞異步型

  阻塞型的IO意味着控制權在調用結束以前不能返回給調用者,這個期間調用者只能作一件事,那就是等着。更讓人不爽的是在等待期間,調用者所在的線程只能眼巴巴的掛在那等着不能幹任何事情,這無疑是很是浪費自願的。

  與此相對的非阻塞同步型的則是當即把控制權返回給調用者。調用者不用等待,它從被調用者那裏獲取兩種可能,要麼成功了進行了,要麼返回給你一個錯誤代碼或者標示之類的東西告訴你沒成功。

  而在非阻塞異步型中,當即返回時,會告訴調用者,你的請求開始了,而且會在完成的時候通知調用者(好比經過回調函數啥的)。

  不用說你們都能看出來,性能最好的是非阻塞異步。

 

  而後咱們來正式說說這兩個多路複用IO方案(Reactor和Proactor)

  通常來講有個東西叫作時間分享器(event demultiplexor),是一個IO複用機須要具有的。它的做用在於把讀寫事件源分發給各讀寫事件的處理人,比如傳達室大爺,負責吼叫每一個人下來拿信件。

  Reactor和Proactor都涉及到這個分享器。其中Reactor是基於同步IO的,可是Proactor是基於異步IO的。他們的區別在於,Reactor等待狀態,一旦能夠讀寫,就經過回調或者通知給預先註冊好的處理者,由矗立着來完成實際的操做;而在Proactor中處理者直接發起一個異步讀寫操做,實際的讀寫是由OS完成的,這種方式在發起的時候就須要提供幾個比較重要的參數,包括用於存放數據的緩存區,讀取數據的大小,回調函數信息等,分離器獲得這個請求後默默地處理,等待完成,而後轉發給相應的處理器去處理。以read操做舉例(write相似)

  Reactor的方式

  • 某個事件處理者註冊它對某個socket上的讀事件很感興趣;
  • 事件分離者等着這個事件的發生;
  • 當事件發生了,事件分離器被喚醒,負責通知先前那個事件處理者;
  • 事件處理者收到消息,因而去那個socket上讀數據了。 若是須要,它再次宣稱對這個socket上的讀事件感興趣,一直重複上面的步驟;

  Proactor的方式

  • 事件處理者直接投遞發一個讀操做(固然,操做系統必須支持這個異步操做)。 這個時候,事件處理者根本不關心讀事件,它只管發這麼個請求,它須要的是這個完成的事件
  • 事件分離者等着這個讀事件的完成(比較下與Reactor的不一樣);
  • 當完成事件到來的同時,操做系統已經開始幹活了,它從目標讀取數據,放入用戶提供的緩存區中,最後通知事件分離者,這個事情完成了;
  • 事件分享者通知以前的事件處理者: 你吩咐的事情搞定了;
  • 事件處理者這時會發現想要讀的數據已經乖乖地放在他提供的緩存區中,想怎麼處理都行了。若是有須要,事件處理者還像以前同樣發起另一個寫操做,和上面的幾個步驟同樣。

  

  而後這兩種方案是否是徹底不能夠調和的呢?答案固然是否認地,調和方案叫作TProactor,關於這個方案,

  http://blog.csdn.net/sparkliang/article/details/5390656博客講的很贊,可是博主聲明未經容許不得轉載,我也就不轉了,你們移步~~~

 

4.異常鏈

  如今咱們拋出一個異常都是能夠包含有原始異常信息的,這對咱們調試代碼很是有幫助,可是1.4之前的JDK,這個工做卻須要程序人員本身搞定,如今全部Throwable的子類子構造器中均可以接受一個cause對象做爲參數,這個cause就異常起因,表明着原始異常,即便在當前位置建立並拋出行的異常,也能夠經過這個cause追蹤到異常最初發生的位置。須要注意的是隻有Error,Exception,RunimeException提供了帶cause參數的構造器,其餘的因此異常就只有經過initCause()來設置cause。

  注意一下幾種形式的異常使用:

  1.這種形式經過initCause設置異常。

Exception bussinessEx = new Exception("packag exception");  
bussinessEx.initCause(ex);      //ex是某個異常
throw bussinessEx; 

  2.這種形式使咱們經常使用的方式

throw new Exception("packag exception", ex);

  3.這種形式是錯誤的!!!throwable 不能是它本身的 cause。

throw (Exception)ex.fillInStackTrace().initCause(ex);

  

5.動態註解(這個詞是這本書中給出的,實際上就是1.5開始支持的註解╮(╯▽╰)╭幹啥非要加個動態....)

  關於註解這東西有多方便,有多牛逼,我相信,誰用過誰知道,那叫一個靈活,Spring那些0配置文件的都靠它了。JDK5的時候開始出現,只有如下這幾個

    1.@Target,
    2.@Retention,
    3.@Documented,
    4.@Inherited

  他們四個是標準的meta-annotation類型,它們被用來提供對其它 annotation類型做說明,被稱爲元註解(也有人說他們是描述註解的註解~~~  )。具體的能我也不想細說了,畢竟這種東西網上海量,提及來也毫無心義,如何靈活運用就看實例了,好比動態數據源切換啥的。

仍是老規矩,不詳細說就貼連接http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html

 

  6.Lambda表達式

  提及Lambda表達式,必須先說明一件事,那就是函數式編程,這個事情不能太展開說,由於萬一展開了,咱就不用回來講Java了,因此只能簡單說(最重要的是看我心情~~  萬一說嗨了那就這麼下去吧)。函數式編程這東西很早就有了,80年的時候吧Haskell就出現了,不過一直都沒有火起來,最近爲何又火起來了呢,主要是大數據時代來了,分佈式來了,愈來愈須要平行的計算,因此能這玩意就又火了,可是幾個大牛又各自看對方不爽,甚至有些本身內部都有撕逼大戰........因此爲了避免出這個黴頭,我趕忙收住,千萬不提那些大牛。說回Java來,Java一看這玩意這麼火Python啥的都開始支持了,我不支持不行啊,這不落後了麼,因此Java也在jdk8中開始對函數式編程支持,也就是lambda表達式。

  (關於函數式編程我給大家貼一個阮一峯的博客~~http://www.ruanyifeng.com/blog/2012/04/functional_programming.html)

  (關於lambda表達式我給大家一個翻譯的文章http://www.cnblogs.com/figure9/archive/2014/10/24/4048421.html)

 

 

  7.Jigsaw(這個我不想說.......拖延症患者........7的時候就說搞,拖到9)

  這東西已經被推到9了.....如今仍是15年底....9預計推出是在16年,不過我卻是以爲這東西9都未必能出.......等着吧.....

  

  8.動態語言支持

  這就是個拽詞....其實意思就是Java7的虛擬機對多種動態程序語言增長了支持,好比:Rubby、 Python等等。對這些動態語言的支持極大地擴展了Java虛擬機的能力。對於那些熟悉這些動態語言的程序員而言,在使用Java虛擬機的過程當中一樣可 以使用它們熟悉的語言進行功能的編寫,而這些語言是跑在功能強大的JVM之上的。僅此而已...............

 

  9.G1垃圾回收器(Garbage-First)

  這東西很牛逼,可是7中還只是實驗階段,好像在8中依然仍是實驗階段,按照openjdk的進度,彷佛9纔會把G1做爲默認的垃圾回收器,要說G1以前,先說說CMS吧,CMS的回收機制是這樣的(原文參考:http://stackvoid.com/Introduce-to-G1/):

  堆被分解爲較小的三個部分。具體分爲:新生代、老年代、持久代。

  

  

  1. 絕大部分新生成的對象都放在Eden區,當Eden區將滿,JVM會因申請不到內存,而觸發Young GC ,進行Eden區+有對象的Survivor區(設爲S0區)垃圾回收,把存活的對象用複製算法拷貝到一個空的Survivor(S1)中,此時Eden 區被清空,另一個Survivor S0也爲空。下次觸發Young GC回收Eden+S0,將存活對象拷貝到S1中。新生代垃圾回收簡單、粗暴、高效。
  2. 若發現Survivor區滿了,則將這些對象拷貝到old區或者Survivor沒滿但某些對象足夠Old,也拷貝到Old區(每次Young GC都會使Survivor區存活對象值+1,直到閾值)。 3.Old區也會進行垃圾收集(Young GC),發生一次 Major GC 至少伴隨一次Young GC,通常比Young GC慢十倍以上。
  3. JVM在Old區申請不到內存,會進行Full GC。Old區使用通常採用Concurrent-Mark–Sweep策略回收內存。

總結:Java垃圾回收器是一種「自適應的、分代的、中止—複製、標記-清掃」式的垃圾回收器。

缺點:

  1. GC過程當中會出現STW(Stop-The-World),若Old區對象太多,STW耗費大量時間。
  2. CMS收集器對CPU資源很敏感。
  3. CMS收集器沒法處理浮動垃圾,可能出現「Concurrent Mode Failure」失敗而致使另外一次Full GC的產生。
  4. CMS致使內存碎片問題。

 

 

再來看看G1是啥樣子的:

  在G1中,堆被劃分紅 許多個連續的區域(region)。每一個區域大小相等,在1M~32M之間。JVM最多支持2000個區域,可推算G1能支持的最大內存爲 2000*32M=62.5G。區域(region)的大小在JVM初始化的時候決定,也能夠用-XX:G1HeapReginSize設置。

  在G1中沒有物理上的Yong(Eden/Survivor)/Old Generation,它們是邏輯的,使用一些非連續的區域(Region)組成的。

  

新生代收集

G1的新生代收集跟ParNew相似,當新生代佔用達到必定比例的時候,開始出發收集。

被圈起的綠色部分爲新生代的區域(region),通過Young GC後存活的對象被複制到一個或者多個區域空閒中,這些被填充的區域將是新的新生代;當新生代對象的年齡(逃逸過一次Young GC年齡增長1)已經達到某個閾值(ParNew默認15),被複制到老年代的區域中。

回收過程是停頓的(STW,Stop-The-Word);回收完成以後根據Young GC的統計信息調整Eden和Survivor的大小,有助於合理利用內存,提升回收效率。

回收的過程多個回收線程併發收集。

 

  

老年代收集

和CMS相似,G1收集器收集老年代對象會有短暫停頓。

  1. 標記階段,首先初始標記(Initial-Mark),這個階段是停頓的(Stop the World Event),而且會觸發一次普通Mintor GC。對應GC log:GC pause (young) (inital-mark)

  2. Root Region Scanning,程序運行過程當中會回收survivor區(存活到老年代),這一過程必須在young GC以前完成。

  3. Concurrent Marking,在整個堆中進行併發標記(和應用程序併發執行),此過程可能被young GC中斷。在併發標記階段,若發現區域對象中的全部對象都是垃圾,那個這個區域會被當即回收(圖中打X)。同時,併發標記過程當中,會計算每一個區域的對象活 性(區域中存活對象的比例)。 JVM4

  4. Remark, 再標記,會有短暫停頓(STW)。再標記階段是用來收集 併發標記階段 產生新的垃圾(併發階段和應用程序一同運行);G1中採用了比CMS更快的初始快照算法:snapshot-at-the-beginning (SATB)。

  5. Copy/Clean up,多線程清除失活對象,會有STW。G1將回收區域的存活對象拷貝到新區域,清除Remember Sets,併發清空回收區域並把它返回到空閒區域鏈表中。                               JVM5

  6. 複製/清除過程後。回收區域的活性對象已經被集中回收到深藍色和深綠色區域。

JVM6

關於Remembered Set概念:G1收集器中,Region之間的對象引用以及其餘收集器中的新生代和 老年代之間的對象引用是使用Remembered Set來避免掃描全堆。G1中每一個Region都有一個與之對應的Remembered Set,虛擬機發現程序對Reference類型數據進行寫操做時,會產生一個Write Barrier暫時中斷寫操做,檢查Reference引用的對象是否處於不一樣的Region之間(在分代中例子中就是檢查是否老年代中的對象引用了新生 代的對象),若是是便經過CardTable把相關引用信息記錄到被引用對象所屬的Region的Remembered Set中。當內存回收時,在GC根節點的枚舉範圍加入Remembered Set便可保證不對全局堆掃描也不會有遺漏。

G1雖然保留了CMS關於代的概念,可是代已經不是物理上連續區域,而是一個邏輯的概念。在標記過程當中,每一個區域的對象活性都被計算,在回收時候, 就能夠根據用戶設置的停頓時間,選擇活性較低的區域收集,這樣既能保證垃圾回收,又能保證停頓時間,並且也不會下降太多的吞吐量。Remark階段新算法 的運用,以及收集過程當中的壓縮,都彌補了CMS不足。引用Oracle官網的一句話:「G1 is planned as the long term replacement for the Concurrent Mark-Sweep Collector (CMS)」。

 

關於這個G1,參考

  1. Memory Management in the Java HotSpot™ Virtual Machine

  2. Getting Started with the G1 Garbage Collector

  3. 垃圾優先型垃圾回收器調優

  4. 深刻理解Java虛擬機:JVM高級特性與最佳實踐

 

 

 

10.Coin(語言細節化)

  名詞挺吊,無非在7的時候就是指

  數字下劃線像這樣

  

public class Coin {
    int test = 123_567; 
    long test1 = 100_000L; 
}

 

  switch語句中的String

public void printDay(String dayOfWeek){
    case "Sunday":System.out.println("ddd");break;
    default:System.out.println("sss");break;
}

  multicatch

public Configuration getConfig(String fileName) {
    Configuration cfg = null;
    try {
      String fileText = getFile(fileName);
      cfg = verifyConfig(parseConfig(fileText));
    } catch (FileNotFoundException | ParseException | ConfigurationException e) {
      System.err.println("Config file '" + fileName
          + "' is missing or malformed");
    } catch (IOException iox) {
      System.err.println("Error while processing file '" + fileName + "'");
    }

    return cfg;
  }

  final重拋

try {
      String fileText = getFile(fileName);
      cfg = verifyConfig(parseConfig(fileText));
    } catch (final Exception  e) {
      throw e;
    }

  try-with-resources(TWR) AutoCloseable

public class Java7ResourcesExample {

  private void run() throws IOException {
    File file = new File("foo");
    URL url = null;
    try {
      url = new URL("http://www.google.com/");
    } catch (MalformedURLException e) {
    }

    try (OutputStream out = new FileOutputStream(file);
        InputStream is = url.openStream()) {
      byte[] buf = new byte[4096];
      int len;
      while ((len = is.read(buf)) > 0) {
        out.write(buf, 0, len);
      }
    }
  }

  public static void main(String[] args) throws IOException {
    Java7ResourcesExample instance = new Java7ResourcesExample();
    instance.run();
  }

}

  所謂的鑽石語法

HashMap<String, String> a = new HashMap<>();

  變參 消失的警告 @SafeVarargs

ublic class Coin {
    int test = 123_567; 
    long test1 = 100_000L;
    
    @SafeVarargs
    public static <T> Collection<T> doSomething(T... entries){
        return null;
    }
    
    public static void main(String[] args) {
        HashMap<String, String> a = new HashMap<>();
        HashMap<String, String> b = new HashMap<>();
        doSomething(a,b);
    }
}

 

 

  實際上還有不少新特性啊,不少關鍵詞啊,只是我無比雞賊的沒有寫出來,僞裝本身不知道,就不用都說了,哈哈哈哈。

相關文章
相關標籤/搜索