Java高級特徵,運行時數據區域,主流對象訪問方式,垃圾收集,判斷一個無用的類,垃圾收集算法,對象優先,部署程式,集群間錯誤,載入和連線,類載入器,執行引擎,編譯過程,解釋器和編譯器,即時編譯器編譯最佳化技術,Java記憶體模型,記憶體間互動操作,執行緒的實現,鎖最佳化,Beand的高級特徵,實現BeanNameAware接口獲取本bean的id屬性,獲取BeanFactory,BeanFactory對象,屬性覆蓋器,Pro/ENGINEER高級特徵,螺旋掃描,可變剖面掃描,掃描混合命令,
Java高級特徵
運行時數據區域
運行時數據區域包括程式計數器、java虛擬機棧、本地方法棧、java堆和方法區。
程式計數器:當前執行緒所執行的位元組碼的行號指示器,改變這個計數器的值來選取下一條需要執行的位元組碼指令;java虛擬機多執行緒是通過執行緒輪流切換並分配處理器執行時間的方式實現,執行緒切換後能恢復到正確的執行位置,所以執行緒私有;native方法的計數器為空
java虛擬機棧:執行緒私有,
生命周期與執行緒相同,每個方法被執行的時候會創建一個棧幀用於存儲局部變數表、操作棧、動態連結、方法出口等,一個方法調用完成的過程就是從入棧到出棧的過程。一般說的棧就是虛擬機棧中的局部變數表,存放編譯期可知的各種基本數據(boolean、byte、char、short、int、float、long、double)、對象引用和returnAdress類型。局部變數表所需的記憶體空間在編譯期間完成分配(完全確定分配多大記憶體),在運行期間不會改變局部變數表的大小,最小單位Slot,每個slot可重用,虛擬機通過索引定位的方式使用局部變數表
本地方法棧:跟虛擬機棧作用相似,虛擬機棧為
虛擬機執行java方法服務,而本地方法棧則為虛擬機使用的native方法服務,sun hotspot虛擬機直接就把兩者合二為一
java堆:被所有執行緒共享的一塊記憶體區域,在虛擬機啟動的時候創建,唯一目的就是存放對象實例;主流虛擬機都是按照可擴展來實現(通過-Xmx和-Xms控制),如果堆中沒有記憶體完成實例分配,並且堆也無法再擴展時將會拋出OutOfMemoryError異常
方法區:執行緒共享的記憶體區域,用於存儲已被
虛擬機載入的類信息、常量、靜態變數、即時編譯器編譯後的代碼等數據;有時稱為永久代,這個區域的記憶體回收目標主要針對常量池的回收和對類型的卸載。運行時常量池是方法區的一部分,用於存放編譯期生成的各種字面量和符號引用,將在類載入後存放到方法區的運行時常量池中;具備動態性,運行期間也可能將新的常量放入池中(如string類的intren()方法)
主流對象訪問方式
主流對象訪問方式:使用句柄和直接指針。
使用句柄,java堆中會將劃分出一塊記憶體來作為句柄池,reference中存儲的就是對象的句柄地址,句柄中包含了對象實例數據(java堆)和類型數據(方法區)各自的具體信息地址;
垃圾收集
垃圾收集:主要指java堆跟方法區,前面三個區域都隨執行緒而生而滅,記憶體在編譯期具備確定性,方法或者執行緒結束就回收了。
堆一般回收一次70-95%,方法區(永久代)主要回收廢棄常量和無用的類
判斷對象是否存活:
jdk1.2後分為強引用、軟引用、弱引用、虛引用;只要強引用還存在,垃圾收集器永遠不會回收掉被引用的對象;軟引用描述一些有用但非必需的對象,其關聯的對象在系統將要發生記憶體溢出異常之前列進回收範圍之中並進行第二次回收;弱引用也是描述非必需對象,只能生存到下一次垃圾收集發生之前;虛引用對其生存時間不構成影響,也無法通過虛引用取得一個對象實例,為一個對象設定虛引用關聯的唯一目的就是希望能在這個對象被收集器回收時收到一個系統通知。
判斷一個無用的類
判斷一個無用的類:該類所有的實例都已經被回收,java堆中不存在該類的任何引用;載入該類的
ClassLoader已經被回收;該類對應的java.lang.Class對象沒有在任何地方被引用,無法在任何地方通過反射該類的方法
垃圾收集算法
標記-清除算法:首先標記出所有需要回收的對象,在標記完成後統一回收掉所有被標記的對象;缺點:效率低,產生大量不連續記憶體碎片占有記憶體。
複製算法:將記憶體按容量劃分大小相等兩塊,每次只使用其中一塊,一塊用完後就將還存活的對象複製到另一塊,然後再把已使用的記憶體空間一次清理掉。
缺點:需要更大記憶體;商業
虛擬機採用此方法回收新生代:分為一塊較大的Eden空間和兩塊小的
Survivor空間,每次使用Eden和其中的一塊Survivor,回收時將這兩塊還存活的對象一次性拷貝到另一塊Survivor空間,最後清理掉Eden和剛才用過的Survivor空間;Eden:Survivor大小默認8:1,如果另一塊Survivor沒有足夠的空間就直接通過分配機制進入年老代。
標記-整理:讓所有存活的對象都向一端移動,然後直接清理掉端邊界以外的記憶體;回收年老代。
分代收集算法:根據對象存活周期的不同將記憶體劃分為幾塊。
對象優先
對象優先在
Eden分配,當沒有足夠空間的時候
虛擬機發起一次minor gc。
大對象直接進入老年代,大對象是指需要大量連續記憶體空間的java對象。
長期存活的對象將進入老年代。
部署程式
高性能硬體上部署程式,主要有兩種方式
集群間錯誤
集群間同步導致的記憶體溢出
堆外記憶體導致的溢出錯誤
外部命令導致系統緩慢
伺服器jam進程崩潰
jps:虛擬機進程狀況工具,可以列出正在運行的虛擬機進程,並顯示虛擬機執行主類的名稱
jstat:虛擬機統計信息監視工具,顯示本地或遠程虛擬機進程中的類裝載、記憶體、垃圾收集、jit編譯等運行數據
jinfo:java配置信息工具,實時查看和調整虛擬機各項參數
jmap:java記憶體映像工具,用於生成堆轉儲快照(dump檔案),還可以查詢finalize執行佇列,java堆和永久代的信息
jhat:虛擬機堆轉儲快照分析工具
jstack:java堆疊跟蹤工具,生成虛擬機當前時刻的執行緒快照,用於定位執行緒出現長時間停頓的原因
載入和連線
java中類型的載入和連線過程都是在程式運行期間完成的
類的整個生命周期:載入、驗證、準備、解析、初始化、使用、卸載
載入:
驗證:連線階段的第一步,為了確保Class檔案中的位元組流中包含的信息符合當前虛擬機的要求,且不會危害虛擬機自身安全。
檔案格式驗證、元數據驗證、位元組碼驗證和符號引用驗證四個階段。
準備:正式為類變數分配記憶體並設定類變數初始值的階段,這些記憶體都將在方法區中進行分配(不包括實例變數的初始化,它將在對象實例化的時候分配在java堆中)。
解析:虛擬機將常量池內的符號引用替換為直接引用的過程
初始化:執行類構造器<clinit>()方法的過程
類載入器
類載入器:啟動類載入器、擴展類載入器、應用程式類載入器
執行引擎
編譯過程
javac編譯過程:解析與填充符號表過程;插入式註解處理器的註解處理過程;分析與位元組碼生成過程
解析與填充符號表:
1)詞法語法分析:詞法分析是將原始碼的字元流轉變為標記(
Token)集合,語法分析是根據Token序列來構造抽象語法樹的過程;
2)填充符號表:符號表由一組符號地址和符號信息構成的表格,可用於語義檢查,地址分配的依據
註解處理器:在處理註解期間對語法樹進行修改,編譯器將回到解析及填充符號表的過程重新處理
語義分析與
位元組碼生成:語義分析的主要任務是對結構上正確的源程式進行上下文有關性質的審查,分為標註檢查和數據及控制流分析兩個步驟;通常使用語法糖能夠增加程式的可讀性,減少代碼出錯的機會;位元組碼生成是java編譯過程最後一個階段,把語法樹、符號表等轉化成位元組碼寫到磁碟中
解釋器和編譯器
當程式需要迅速啟動和執行的時候,
解釋器可以首先發揮作用,省去編譯的時間,立即執行;當程式運行後,隨著時間推移,編譯器逐漸發揮作用,把越來越多的代碼編譯成本地代碼之後,可以獲取更高的執行效率。
hotspot虛擬機內置量兩個即時編譯器client compiler和server compiler,採用分層編譯的策略。
“熱點代碼”會被即時編譯器編譯:被多次調用的方法;被多次執行的循環體。熱點探測:基於採樣;基於計數器(方法調用計數器,回邊計數器)。
即時編譯器編譯最佳化技術
1)方法內聯:除去方法調用成本,為其他最佳化建立良好基礎
2)進行冗餘訪問消除
3)複寫傳播
4)無用代碼消除
5)公共子表達式消除
6)數組邊界檢查消除
7)逃逸分析
Java記憶體模型
Java記憶體模型:禁止各種硬體和作業系統的記憶體訪問差異,以實現讓java程式在各種平台下都能達到一致的並發效果。
主記憶體與工作記憶體:每條執行緒的工作記憶體保存了該執行緒使用到的變數的主記憶體副本拷貝,執行緒對變數的所有操作都必須在工作記憶體中進行
記憶體間互動操作
記憶體間互動操作:lock(鎖定)、unlock(解鎖)、read(讀取)、load(載入)、use(使用)、assign(賦值)、store(存儲)、write(寫入)
volatile:一個變數定義成
volatile之後,具備兩種特性,第一是保證此變數對所有執行緒的可見性;但並發下並一定是安全的,因為java裡面的運算操作並非原子操作,由於volatile變數只能保證可見性,在不符合以下兩條規則的運算場景中,仍需要通過加鎖(使用synchronized或java.util.concurrent中的原子類)來保證原子性。
1)運算結果並不依賴變數的當前值,或者確保只有單一的執行緒修改變數值
2)變數不需要與其他狀態變數共同參與不變約束
第二個特性是禁止指令重排序最佳化。
volatile變數的讀操作的性能消耗與普通變數幾乎沒啥差別,但是寫操作可能會慢一些,因為需要在本地代碼中插入許多記憶體屏障指令來保證處理器不發生亂序執行,在volatile與鎖中選擇的唯一判斷依據僅僅是volatile的語義能否滿足使用場景的需求
允許
虛擬機將沒有被volatile修飾的64位數據的讀寫操作劃分為兩次32位的操作來進行,即允許虛擬機實現選擇可以不保證64位數據類型的load、store、read、write這四個操作的原子性,這就是所謂的long或double的非原子性協定,目前商用虛擬機幾乎把64位數據的讀寫操作作為原子操作來對待
java記憶體模型圍繞在並發過程中如何處理原子性、可見性和有序性三個特性來建立的。
可見性:(volatile、synchronized和final修飾)
有序性:執行緒內表現為串列的語義,觀察另一個執行緒則是無序的
執行緒的實現
執行緒的實現主要有三種方式:使用核心執行緒實現,使用用戶執行緒實現,使用用戶執行緒加輕量級進程混合實現
一條java執行緒就映射到一條輕量級進程之中,執行緒調度是指系統為執行緒分配處理器使用權的過程,主要調度
方式有兩種:協同式執行緒調度和搶占式執行緒調度,java使用搶占式,java執行緒是被映射到作業系統的原生執行緒上來實現的,執行緒調度最終還是由作業系統說了算
java進程5個狀態,任一時刻有且只有一種狀態:新建、運行、無限期等待、限期等待、
阻塞、結束
java中各種操作共享的數據分為五類:不可變、絕對執行緒安全、相對執行緒安全、執行緒兼容和執行緒對立
執行緒安全的實現方法:互斥同步(悲觀)、非阻塞同步(樂觀)、無同步方案
鎖最佳化
1)自旋鎖與自適應自旋
2)鎖消除
3)鎖粗化
4)輕量級鎖
5)偏向鎖
Beand的高級特徵
Spring程式中,Java Bean一般與Spring是非耦合的,不會依賴於
Spring類庫。這也是Spring的優點。
實現BeanNameAware接口獲取本bean的id屬性
BeanNameAware中一個方法setBeanName(String arg0);它會在bean所有參數設定後 init-method之前調用,在bean中聲明一個屬性接受。
獲取BeanFactory
實現BeanFactoryAware可以獲取該bean對應的BeanFactory。
demo:
View Code
實現DisposableBean接口執行銷毀方法。
被bean中的destory-method屬性替代,一般不使用
實現InitializingBean接口執行初始化方法。
被bean的init-method屬性替代,一般不使用
BeanFactory對象
BeanFactory對象的幾個常用的方法:
boolean containsBean(String):判斷指定名稱的Bean是否存在
Object getBean(String):返回指定名稱的Bean。如果沒有,會拋出異常
Object getBean(String,Class):返回指定名稱的Bean,並進行類型轉換成類對象。兩個過程中出錯都會異常
boolean isSingleton(String):判斷指定名稱的
Bean是否配置為singleton。沒有bean,拋出異常
String[] getAliases(String):獲取指定名稱bean的所有別名的數組
屬性覆蓋器
對於一些參數,更實用更簡單的方法是使用properties配置,而不是配置在Spring的配置檔案中。Spring提供屬性替代屬性,允許把某些屬性配置在properties檔案中。
配置PropertyOverrideConfigurer屬性覆蓋器
PropertyOverrideConfigure允許把
XML配置里的魔偶寫參數配置到properties檔案中。這些在資料庫配置中很常用。配置時需要配置一個PropertyOverrideConfigure對象,指定properties檔案的位置,然後把替換的屬性用形如${jdbc.url}的字元串替代。
Pro/ENGINEER高級特徵
Pro/
ENGINEER的高級特徵實現了複雜曲面的數位化表示,使難以描述的複雜模型變得直觀明了而且非常精確。利用Pro/ENGINEER的零件高級
建模功能可以設計外形複雜的產品,從機械產品中的彈簧、螺紋到工業造型設計中的手機外殼、
顯示器等,都離不開高級特徵的使用。可以說,Pro/ENGINEER的高級特徵對工業造型設計人員來說是必不可少的得力助手,它大大提高了產品設計的效率和質量。
螺旋掃描
螺旋掃描,即用一個截面沿著螺旋軌跡掃描來創建特徵,它通過旋轉曲面的輪廓和螺距兩者來定義軌跡。螺旋軌跡和旋轉曲面只是一種作圖工具,它們不會出現在生成的特徵中。
螺旋掃描功能可用於實體伸出、實體切口、薄殼伸出和切口,以及曲面及曲面修剪等特徵。從主選單〖插入〗|〖螺旋掃描〗|〖伸出〗,在〖屬性〗選單中,對成對出現的命令(只能選擇其一)進行選擇來定義螺旋掃描特徵。
〖常量〗螺距為常數。
〖變數〗螺距是可變的,並由某圖形定義。
〖穿過軸〗橫截面位於穿過旋轉軸的平面內。
〖軌跡法向〗確定橫截面方向,使之垂直於軌跡或旋轉面。
〖右手定則〗使用右手定則定義軌跡,即右旋。
〖左手定則〗使用左手定則定義軌跡,即左旋。
可變剖面掃描
可變剖面掃描允許截面沿所選的多條軌跡運動來創建特徵,截面在運動過程中其形狀沿著
軌跡線變化。多條軌跡線中,一條
軌跡線控制截面的運動路線,其他幾條軌跡線控制截面的形狀,截面在運動過程中,並一定垂直於軌跡線。
使用可變剖面掃描功能,必須先繪製軌跡線。然後從主選單〖插入〗|〖變剖面掃描〗,或從工具列中選擇按鈕,彈出可變剖面掃描操控板。可進行實體的伸出和切除、曲面及修剪、薄殼等特徵。
〖參照〗用於選取軌跡線及對截面運動的控制方式,點擊彈出上滑面板。
掃描混合命令
掃描混合命令使用一條軌跡線與幾個剖面來創建一個實體特徵,同時具有掃描和混合的效果。
選擇
主選單〖插入〗|〖螺旋掃描〗|〖伸出〗,出現圖7.28所示的選單管理器。 掃描混合的截面放置方式與可變截面掃描相似:
垂直於原始軌跡:截面垂直於原始軌跡線上該截面放置點的切矢量,即確定Z軸。
軸心方向:截面垂直於原始軌跡線,並沿指定的方向掃描。