編譯器的分析模型包含哪些部分
① 技術解析Transwarp Inceptor是怎樣煉成的
技術解析Transwarp Inceptor是怎樣煉成的
當前Hadoop技術蓬勃發展,用於解決大數據的分析難題的技術平台開始涌現。Spark憑借性能強勁、高度容錯、調度靈活等技術優勢已漸漸成為主流技術,業界大部分廠商都提供了基於Spark的技術方案和產品。根據Databricks的統計,目前有11個商業的Spark版本。
在使用Spark作出計算平台的解決方案中,有兩種主流編程模型,一類是基於SparkAPI或者衍生出來的語言,另一種是基於SQL語言。SQL作為資料庫領域的事實標准語言,相比較用API(如MapReceAPI,SparkAPI等)來構建大數據分析的解決方案有著先天的優勢:一是產業鏈完善,各種報表工具、ETL工具等可以很好的對接;二是用SQL開發有更低的技術門檻;三是能夠降低原有系統的遷移成本等。因此,SQL語言也漸漸成為大數據分析的主流技術標准。本文將深入解析Inceptor的架構、編程模型和編譯優化技術,並提供基準測試在多平台上的性能對比數據。
1.Inceptor架構
TranswarpInceptor是基於Spark的分析引擎,如圖1所示,從下往上有三層架構:最下面是存儲層,包含分布式內存列式存儲(TranswarpHolodesk),可建在內存或者SSD上;中間層是Spark計算引擎層,星環做了大量的改進保證引擎有超強的性能和高度的健壯性;最上層包括一個完整的SQL99和PL/SQL編譯器、統計演算法庫和機器學習演算法庫,提供完整的R語言訪問介面。
TranswarpInceptor可以分析存儲在HDFS、HBase或者TranswarpHolodesk分布式緩存中的數據,可以處理的數據量從GB到數十TB,即使數據源或者中間結果的大小遠大於內存容量也可高效處理。另外TranswarpInceptor通過改進Spark和YARN的組合,提高了Spark的可管理性。同時星環不僅僅是將Spark作為一個預設計算引擎,也重寫了SQL編譯器,提供更加完整的SQL支持。
同時,TranswarpInceptor還通過改進Spark使之更好地與HBase融合,可以為HBase提供完整的SQL支持,包括批量SQL統計、OLAP分析以及高並發低延時的SQL查詢能力,使得HBase的應用可以從簡單的在線查詢應用擴展到復雜分析和在線應用結合的混合應用中,大大拓展了HBase的應用范圍。
2.編程模型
TranswarpInceptor提供兩種編程模型:一是基於SQL的編程模型,用於常規的數據分析、數據倉庫類應用市場;二是基於數據挖掘編程模型,可以利用R語言或者SparkMLlib來做一些深度學習、數據挖掘等業務模型。
2.1SQL模型
TranswarpInceptor實現了自己的SQL解析執行引擎,可以兼容SQL99和HiveQL,自動識別語法,因此可以兼容現有的基於Hive開發的應用。由於TranswarpInceptor完整支持標準的SQL 99標准,傳統資料庫上運行的業務可以非常方便的遷移到Transwarp Inceptor系統上。此外Transwarp Inceptor支持PL/SQL擴展,傳統數據倉庫的基於PL/SQL存儲過程的應用(如ETL工具)可以非常方便的在Inceptor上並發執行。另外Transwarp Inceptor支持部分SQL 2003標准,如窗口統計功能、安全審計功能等,並對多個行業開發了專門的函數庫,因此可以滿足多個行業的特性需求。
2.2數據挖掘計算模型
TranswarpInceptor實現了機器學習演算法庫與統計演算法庫,支持常用機器學習演算法並行化與統計演算法並行化,並利用Spark在迭代計算和內存計算上的優勢,將並行的機器學習演算法與統計演算法運行在Spark上。例如:機器學習演算法庫有包括邏輯回歸、樸素貝葉斯、支持向量機、聚類、線性回歸、關聯挖掘、推薦演算法等,統計演算法庫包括均值、方差、中位數、直方圖、箱線圖等。TranswarpInceptor可以支持用R語言或者SparkAPI在平台上搭建多種分析型應用,例如用戶行為分析、精準營銷、對用戶貼標簽、進行分類。
3.SQL編譯與優化
TranswarpInceptor研發了一套完整的SQL編譯器,包括HiveQL解析器、SQL標准解析器和PL/SQL解析器,將不同的SQL語言解析成中間級表示語言,然後經過優化器轉換成物理執行計劃。SQL語言解析後經過邏輯優化器生成中間級表示語言,而中間表示語言再經過物理優化器生成最終的物理執行計劃。從架構上分,邏輯優化器和物理優化器都包含基於規則的優化模塊和基於成本的優化模塊。
為了和Hadoop生態更好的兼容,Inceptor為一個SQL查詢生成MapRece上的執行計劃和Spark上的執行計劃,並且可以通過一個SET命令在兩種執行引擎之間切換。
3.1SQL編譯與解析
TranswarpInceptor的SQL編譯器會根據輸入的SQL查詢的類型來自動選擇不同的解析器,如PL/SQL存儲過程會自動進入PL/SQL解析器並生成一個SparkRDD的DAG從而在Spark平台上並行計算,標准SQL查詢會進入SQL標准解析器生成Spark或MapRece執行計劃。由於HiveQL和標準的SQL有所出入,為了兼容HiveQL,Transwarp Inceptor保留了HiveQL解析器,並可以對非標准SQL的Hive查詢生成Spark或者Map Rece執行計劃。
3.1.1SQL標准解析器
TranswarpInceptor構建了自主研發的SQL標准解析器,用於解析SQL99& SQL 2003查詢並生成Spark和Map Rece的執行計劃。詞法和語法分析層基於Antlr語法來構建詞法範式,通過Antlr來生成抽象語義樹,並會通過一些上下文的語義來消除沖突並生成正確的抽象語義樹。語義分析層解析上層生成的抽象語義樹,根據上下文來生成邏輯執行計劃並傳遞給優化器。首先Transwarp Inceptor會將SQL解析成TABLE SCAN、SELECT、FILTER、JOIN、UNION、ORDER BY、GROUP BY等主要的邏輯塊,接著會根據一些Meta信息進一步細化各個邏輯塊的執行計劃。如TABLE SCAN會分成塊讀取、塊過濾、行級別過濾、序列化等多個執行計劃。
3.1.2PL/SQL解析器
PL/SQL是Oracle對SQL語言的模塊化擴展,已經在很多行業中有大規模的應用,是數據倉庫領域的重要編程語言。
為了讓存儲過程在Spark上有較好的性能,PL/SQL解析器會根據存儲過程中的上下文關系來生成SQLDAG,然後對各SQL的執行計劃生成的RDD進行二次編譯,通過物理優化器將一些沒有依賴關系的RDD進行合並從而生成一個最終的RDDDAG。因此,一個存儲過程被解析成一個大的DAG,從而stage之間可以大量並發執行,避免了多次執行SQL的啟動開銷並保證了系統的並發性能。
解析並生成SQL級別的執行計劃
3.2SQL優化器
TranswarpInceptor使用Spark作為默認計算引擎,並且開發了完善的SQL優化器,因此在大量的客戶案例性能測試中,TranswarpInceptor的性能領先MapRece 10-100倍,並超越部分開源MPP資料庫。SQL優化器對平台性能的提升居功至偉。
3.2.1基於規則的優化器(RuleBasedOptimizer)
目前為止,TranswarpInceptor共實現了一百多個優化規則,並且在持續的添加新的規則。按照功能劃分,這些規則主要分布在如下幾個模塊:
文件讀取時過濾
在文件讀取時過濾數據能夠最大化的減少參與計算的數據量從而最為有效的提高性能,因此TranswarpInceptor提供了多個規則用於生成表的過濾條件。對於一些SQL中的顯示條件,TranswarpInceptor會盡量將過濾前推到讀取表中;而對於一些隱式的過濾條件,如可以根據joinkey生成的過濾規則,Inceptor會根據語義保證正確性的前提下進行規則生成。
過濾條件前置
TranswarpInceptor能夠從復雜的組合過濾條件中篩選出針對特定表的過濾規則,然後通過SQL語義來確定是否能將過濾條件前推到盡量早的時候執行。如果有子查詢,過濾條件可以遞歸前推入最低層的子查詢中,從而保證所有的冗餘數據被刪除。
超寬表的讀取過濾
對一些列超多的表進行處理的時候,TranswarpInceptor首先會根據SQL語義來確定要讀取的列,並在讀取表的時候進行跨列讀取減少IO和內存消耗。而如果表有過濾條件,Inceptor會做進一步優化,首先只讀取過濾條件相關的列來確定該行記錄是否需要被選擇,如果不是就跳過當前行的所有列,因此能夠最大程度上的減少數據讀取。在一些商業實施中,這些優化規則能夠帶來5x-10x的性能提升。
Shuffle Stage的優化與消除
Spark的shuffle實現的效率非常低,需要把結果寫磁碟,然後通過HTTP傳輸。TranswarpInceptor添加了一些shuffle消除的優化規則,對SQL的DAG中不必要或者是可以合並的shufflestage進行消除或者合並。對於必須要做Shuffle的計算任務,Inceptor通過DAGScheler來提高shuffle的效率:MapTask會直接將結果返回給DAGScheler,然後DAGScheler將結果直接交給Rece Task而不是等待所有Map Task結束,這樣能夠非常明顯的提升shuffle階段的性能。
Partition消除
TranswarpInceptor提供單一值Partition和RangePartition,並且支持對Partition建Bucket來做多次分區。當Partition過多的時候,系統的性能會因為內存消耗和調度開銷而損失。因此,Inceptor提供了多個規則用於消除不必要的Partition,如果上下文中有隱式的對Partition的過濾條件,Inceptor也會生成對partition的過濾規則。
3.2.2基於成本的優化器(CostBasedOptimizer)
基於規則的優化器都是根據一些靜態的信息來產生的,因此很多和動態數據相關的特性是不能通過基於規則的優化來解決,因此TranswarpInceptor提供了基於成本的優化器來做二次優化。相關的原始數據主要來自Meta-store中的表統計信息、RDD的信息、SQL上下文中的統計信息等。依賴於這些動態的數據,CBO會計算執行計劃的物理成本並選擇最有效的執行計劃。一些非常有效的優化規則包括如下幾點:
JOIN順序調優
在實際的案例中,join是消耗計算量最多的業務,因此對join的優化至關重要。在多表JOIN模型中,TranswarpInceptor會根據統計信息來預估join的中間結果大小,並選擇產生中間數據量最小的join順序作為執行計劃。
JOIN類型的選擇
TranswarpInceptor支持Left-mostJoinTree 和 Bush Join Tree,並且會根據統計信息來選擇生成哪種Join模型有最佳性能。此外,Transwarp Inceptor會根據原始表或者中間數據的大小來選擇是否開啟針對數據傾斜模型下的特殊優化等。此外,針對HBase表是否有索引的情況,Transwarp Inceptor會在普通Join和Look-up Join間做個均衡的選擇。
並發度的控制
Spark通過線程級並發來提高性能,但是大量的並發可能會帶來不必要的調度開銷,因此不同的案例在不同並發度下會有最佳性能。TranswarpInceptor通過對RDD的一些屬性進行推算來選擇最佳並發控制,對很多的案例有著2x-3x的性能提升。
4.TranswarpHolodesk內存計算引擎
為了有效的降低SQL分析的延時,減少磁碟IO對系統性能的影響,星環科技研發了基於內存或者SSD的存儲計算引擎TranswarpHolodesk,通過將表數據直接建在內存或者SSD上以實現SQL查詢全內存計算。另外TranswarpHolodesk增加了數據索引功能,支持對多個數據列建索引,從而更大程度的降低了SQL查詢延時。
4.1存儲格式
TranswarpHolodesk基於列式存儲做了大量的原創性改進帶來更高的性能和更低的數據膨脹率。首先數據被序列化後存儲到內存或SSD上以節省者資源佔用。如圖3所示,每個表的數據被存儲成若干個Segment,每個Segment被劃分成若干個Block,每個Block按照列方式存儲於SSD或內存中。另外每個Block的頭部都加上Min-MaxFilter和BloomFilter用於過濾無用的數據塊,減少不必要的數據進入計算階段。
TranswarpHolodesk根據查詢條件的謂詞屬性對每個數據塊的對應列構建數據索引,索引列採用自己研發的Trie結構進行組織存儲,非索引列採用字典編碼的方式進行組織存儲。Trie不僅能對具有公共前綴的字元串進行壓縮,而且可以對輸入的字元串排序,從而可以利用二分查找快速查詢所需數據的位置,從而快速響應查詢需求。
HDFS2.6支持StorageTier讓應用程序可以選擇存儲層為磁碟或者SSD,但是沒有專用的存儲格式設計是無法有效利用SSD的讀寫吞吐量和低延,因此現有的Text以及行列混合(ORC/Parquet)都不能有效的利用SSD的高性能。為此驗證存儲結構對性能的影響,我們將HDFS構建在SSD上並選用某基準測試來做了進一步的性能對比,結果如圖4所示:採用文本格式,PCI-ESSD帶來的性能提升僅1.5倍;採用專為內存和SSD設計的Holodesk列式存儲,其性能相比較SSD上的HDFS提升高達6倍。
4.2性能優勢
某運營商客戶在12台x86伺服器上搭建了TranswarpInceptor,將TranswarpHolodesk配置在PCIE-SSD上,並與普通磁碟表以及DB2來做性能對比測試。最終測試數據如圖5所示:
在純粹的count測試一項,Holodesk性能相對於磁碟表最高領先32倍;對於join測試一項,TranswarpHolodesk最高領先磁碟表多達12倍;在單表聚合測試中,Holodesk提升倍數達10~30倍。另外TranswarpHolodesk在和DB2的對比中也表現優秀,兩個復雜SQL查詢在DB2資料庫中需要運行1小時以上,但是在使用TranswarpHolodesk均是分鍾級和秒級就返回結果。
內存的價格大約是同樣容量SSD的十倍左右,為了給企業提供更高性價比的計算方案,TranswarpHolodesk針對SSD進行了大量的優化,使得應用在SSD上運行具有與在內存上比較接近的性能,從而為客戶提供了性價比更高的計算平台。
在對TPC-DS的IO密集型查詢的測試中,無論上構建在PCI-ESSD還是內存上,Holodesk對比磁碟表有一個數量級上的性能提升;而SSD上的Holodesk性能只比內存差10%左右。
5.穩定的Spark執行引擎
企業目前應用開源Spark的主要困難在穩定性、可管理性和功能不夠豐富上。開源Spark在穩定性上還有比較多的問題,在處理大數據量時可能無法運行結束或出現Outofmemory,性能時快時慢,有時比Map/Rece更慢,無法應用到復雜數據分析業務中。
TranswarpInceptor針對各種出錯場景設計了多種解決方法,如通過基於成本的優化器選擇最合適的執行計劃、加強對數據結構內存使用效率的有效管理、對常見的內存出錯問題通過磁碟進行數據備份等方式,極大提高了Spark功能和性能的穩定性,上述問題都已經解決並經過商業案例的考驗。TranswarpInceptor能穩定的運行7*24小時,並能在TB級規模數據上高效進行各種穩定的統計分析。
6.SQL引擎效能驗證
TPC-DS是TPC組織為DecisionSupportSystem設計的一個測試集,包含對大數據集的統計/報表生成/聯機查詢/數據挖掘等復雜應用,測試用的數據有各種不同的分布與傾斜,與真實場景非常接近。隨著國內外各代表性的Hadoop發行版廠商以TPC-DS為標准測評產品,TPC-DS也就逐漸成為了業界公認的Hadoop系統測試准則。
6.1驗證對比的平台和配置
我們搭建了兩個集群分別用於TranswarpInceptor與ClouderaDataHub/Impala的測試。
6.2TranswarpInceptorVS Cloudera Impala
TranswarpInceptor由於有完善的SQL支持,能夠運行全部所有的99個SQL查詢。而由於Cloudera官方發布的TPC-DS測試集只包含19個SQL案例,因此我們只能運行這19個SQL,實驗證明這部分查詢在Impala上全部正常運行完成。
6.3TranswarpInceptorVS Map Rece
我們使用了同樣的硬體和軟體配置完成和開源的Hive執行效率相比,TranswarpInceptor能夠帶來10x-100x的性能提升。圖8是TPC-DS的部分SQL查詢在Inceptor和CDH5.1Hive的性能提升倍數,其中最大的提升倍數竟可達到123倍。
7.結語
隨著在大數據領域國內外開始處於同一起跑線,我們相信像星環科技這樣國內具有代表性的Hadoop發行版廠商將在中國的廣闊市場空間中獲得長足發展,並且由於中國市場激烈的競爭與磨練,逐步打磨出超越國外先進廠商的技術與實力。
劉汪根。2013年加入星環,作為早期員工參與了星環大數據平台的構建,現擔任數據平台部研發經理,主要負責與管理星環大數據平台數據平台的研發工作,如SQL編譯器,Spark執行引擎等工作,產品涵括TranswarpInceptor/TranswarpStream等軟體。
【編者按】星環科技從2013年6月開始研發基於Spark的SQL執行引擎,在2013年底推出TranswarpInceptor1.0,並落地了國內首個7x24小時的商用項目。經過1年多的持續創新與改進,星環已經在國內落地了數十個Inceptor的商用項目。這是一篇星環Spark解決方案的技術解析,也是Spark用戶可以效仿的優化之道。
② 了解什麼叫做jit compiling,與傳統的編譯技術有何不同
java 應用程序的性能經常成為開發社區中的討論熱點。因為該語言的設計初衷是使用解釋的方式支持應用程序的可移植性目標,早期
Java 運行時所提供的性能級別遠低於 C 和
C++
之類的編譯語言。盡管這些語言可以提供更高的性能,但是生成的代碼只能在有限的幾種系統上執行。在過去的十年中,Java
運行時供應商開發了一些復雜的動態編譯器,通常稱作即時(Just-in-time,JIT)編譯器。程序運行時,JIT
編譯器選擇將最頻繁執行的方法編譯成本地代碼。運行時才進行本地代碼編譯而不是在程序運行前進行編譯(用 C 或
C++ 編寫的程序正好屬於後一情形),保證了可移植性的需求。有些 JIT 編譯器甚至不使用解釋程序就能編譯所有的代碼,但是這些編譯器仍然通過在程序執行時進行一些操作來保持 Java 應用程序的可移植性。
由於動態編譯技術的多項改進,在很多應用程序中,現代的 JIT 編譯器可以產生與 C 或 C++
靜態編譯相當的應用程序性能。但是,仍然有很多軟體開發人員認為 —— 基於經驗或者傳聞 ——
動態編譯可能嚴重干擾程序操作,因為編譯器必須與應用程序共享 CPU。一些開發人員強烈呼籲對 Java
代碼進行靜態編譯,並且堅信那樣可以解決性能問題。對於某些應用程序和執行環境而言,這種觀點是正確的,靜態編譯可以極大地提高 Java
性能,或者說它是惟一的實用選擇。但是,靜態地編譯 Java 應用程序在獲得高性能的同時也帶來了很多復雜性。一般的
Java 開發人員可能並沒有充分地感受到 JIT 動態編譯器的優點。
本文考察了 Java 語言靜態編譯和動態編譯所涉及的一些問題,重點介紹了實時 (RT) 系統。簡要描述了 Java
語言解釋程序的操作原理並說明了現代 JIT 編譯器執行本地代碼編譯的優缺點。介紹了 IBM 在 WebSphere Real Time 中發布的
AOT 編譯技術和它的一些優缺點。然後比較了這兩種編譯策略並指出了幾種比較適合使用 AOT
編譯的應用程序領域和執行環境。要點在於這兩種編譯技術並不互斥:即使在使用這兩種技術最為有效的各種應用程序中,它們也分別存在一些影響應用程序的優缺
點。
執行 Java 程序
Java 程序最初是通過 Java SDK 的 javac程序編譯成本地的與平台無關的格式(類文件)。可將此格式看作 Java
平台,因為它定義了執行 Java 程序所需的所有信息。Java 程序執行引擎,也稱作 Java 運行時環境(JRE),包含了為特定的本地平台實現
Java 平台的虛擬機。例如,基於 Linux 的 Intel x86 平台、Sun Solaris 平台和 AIX 操作系統上運行的 IBM
System p 平台,每個平台都擁有一個 JRE。這些 JRE 實現實現了所有的本地支持,從而可以正確執行為
Java 平台編寫的程序。
事實上,操作數堆棧的大小有實際限制,但是編程人員極少編寫超出該限制的方法。JVM 提供了安全性檢查,對那些創建出此類方法的編程人員進行通知。
Java 平台程序表示的一個重要部分是位元組碼序列,它描述了 Java
類中每個方法所執行的操作。位元組碼使用一個理論上無限大的操作數堆棧來描述計算。這個基於堆棧的程序表示提供了平台無關性,因為它不依賴任何特定本地平台
的 CPU 中可用寄存器的數目。可在操作數堆棧上執行的操作的定義都獨立於所有本地處理器的指令集。Java
虛擬機(JVM)規范定義了這些位元組碼的執行(參見 參考資料)。執行 Java 程序時,用於任何特定本地平台的任何 JRE 都必須遵守 JVM
規范中列出的規則。
因為基於堆棧的本地平台很少(Intel X87 浮點數協處理器是一個明顯的例外),所以大多數本地平台不能直接執行 Java 位元組碼。為了解決這個問題,早期的 JRE 通過解釋位元組碼來執行 Java 程序。即 JVM 在一個循環中重復操作:
◆獲取待執行的下一個位元組碼;
◆解碼;
◆從操作數堆棧獲取所需的操作數;
◆按照 JVM 規范執行操作;
◆將結果寫回堆棧。
這種方法的優點是其簡單性:JRE 開發人員只需編寫代碼來處理每種位元組碼即可。並且因為用於描述操作的位元組碼少於 255 個,所以實現的成本比較低。當然,缺點是性能:這是一個早期造成很多人對 Java 平台不滿的問題,盡管擁有很多其他優點。
解決與 C 或 C++ 之類的語言之間的性能差距意味著,使用不會犧牲可移植性的方式開發用於 Java 平台的本地代碼編譯。
編譯 Java 代碼
盡管傳聞中 Java 編程的 「一次編寫,隨處運行」
的口號可能並非在所有情況下都嚴格成立,但是對於大量的應用程序來說情況確實如此。另一方面,本地編譯本質上是特定於平台的。那麼 Java
平台如何在不犧牲平台無關性的情況下實現本地編譯的性能?答案就是使用 JIT 編譯器進行動態編譯,這種方法已經使用了十年(參見圖 1):
圖 1. JIT 編譯器
使用 JIT 編譯器時,Java
程序按每次編譯一個方法的形式進行編譯,因為它們在本地處理器指令中執行以獲得更高的性能。此過程將生成方法的一個內部表示,該表示與位元組碼不同但是其級
別要高於目標處理器的本地指令。(IBM JIT
編譯器使用一個表達式樹序列表示方法的操作。)編譯器執行一系列優化以提高質量和效率,最後執行一個代碼生成步驟將優化後的內部表示轉換成目標處理器的本
地指令。生成的代碼依賴運行時環境來執行一些活動,比如確保類型轉換的合法性或者對不能在代碼中直接執行的某些類型的對象進行分配。JIT
編譯器操作的編譯線程與應用程序線程是分開的,因此應用程序不需要等待編譯的執行。
圖 1 中還描述了用於觀察執行程序行為的分析框架,通過周期性地對線程取樣找出頻繁執行的方法。該框架還為專門進行分析的方法提供了工具,用來存儲程序的此次執行中可能不會改變的動態值。
因為這個 JIT 編譯過程在程序執行時發生,所以能夠保持平台無關性:發布的仍然是中立的 Java 平台代碼。C 和 C++ 之類的語言缺乏這種優點,因為它們在程序執行前進行本地編譯;發布給(本地平台)執行環境的是本地代碼。
挑戰
盡管通過 JIT 編譯保持了平台無關性,但是付出了一定代價。因為在程序執行時進行編譯,所以編譯代碼的時間將計入程序的執行時間。任何編寫過大型 C 或 C++ 程序的人都知道,編譯過程往往較慢。
為了克服這個缺點,現代的 JIT
編譯器使用了下面兩種方法的任意一種(某些情況下同時使用了這兩種方法)。第一種方法是:編譯所有的代碼,但是不執行任何耗時多的分析和轉換,因此可以快
速生成代碼。由於生成代碼的速度很快,因此盡管可以明顯觀察到編譯帶來的開銷,但是這很容易就被反復執行本地代碼所帶來的性能改善所掩蓋。第二種方法是:
將編譯資源只分配給少量的頻繁執行的方法(通常稱作熱方法)。低編譯開銷更容易被反復執行熱代碼帶來的性能優勢掩蓋。很多應用程序只執行少量的熱方法,因
此這種方法有效地實現了編譯性能成本的最小化。
動態編譯器的一個主要的復雜性在於權衡了解編譯代碼的預期獲益使方法的執行對整個程序的性能起多大作用。一個極端的例子是,程序執行後,您非常清楚哪些方
法對於這個特定的執行的性能貢獻最大,但是編譯這些方法毫無用處,因為程序已經完成。而在另一個極端,程序執行前無法得知哪些方法重要,但是每種方法的潛
在受益都最大化了。大多數動態編譯器的操作介於這兩個極端之間,方法是權衡了解方法預期獲益的重要程度。
Java 語言需要動態載入類這一事實對 Java
編譯器的設計有著重要的影響。如果待編譯代碼引用的其他類還沒有載入怎麼辦?比如一個方法需要讀取某個尚未載入的類的靜態欄位值。Java
語言要求第一次執行類引用時載入這個類並將其解析到當前的 JVM
中。直到第一次執行時才解析引用,這意味著沒有地址可供從中載入該靜態欄位。編譯器如何處理這種可能性?編譯器生成一些代碼,用於在沒有載入類時載入並解
析類。類一旦被解析,就會以一種線程安全的方式修改原始代碼位置以便直接訪問靜態欄位的地址,因為此時已獲知該地址。
IBM JIT
編譯器中進行了大量的努力以便使用安全而有效率的代碼補丁技術,因此在解析類之後,執行的本地代碼只載入欄位的值,就像編譯時已經解析了欄位一樣。另外一
種方法是生成一些代碼,用於在查明欄位的位置以前一直檢查是否已經解析欄位,然後載入該值。對於那些由未解析變成已解析並被頻繁訪問的欄位來說,這種簡單
的過程可能帶來嚴重的性能問題。
動態編譯的優點
動態地編譯 Java 程序有一些重要的優點,甚至能夠比靜態編譯語言更好地生成代碼,現代的 JIT 編譯器常常向生成的代碼中插入掛鉤以收集有關程序行為的信息,以便如果要選擇方法進行重編譯,就可以更好地優化動態行為。
關於此方法的一個很好的例子是收集一個特定 array操作的長度。如果發現每次執行操作時該長度基本不變,則可以為最頻繁使用的
array長度生成專門的代碼,或者可以調用調整為該長度的代碼序列。由於內存系統和指令集設計的特性,用於復制內存的最佳通用常式的執行速度通
常比用於復制特定長度的代碼慢。例如,復制 8
個位元組的對齊的數據可能需要一到兩條指令直接復制,相比之下,使用可以處理任意位元組數和任意對齊方式的一般復制循環可能需要 10 條指令來復制同樣的 8
個位元組。但是,即使此類專門的代碼是為某個特定的長度生成的,生成的代碼也必須正確地執行其他長度的復制。生成代碼只是為了使常見長度的操作執行得更快,
因此平均下來,性能得到了改進。此類優化對大多數靜態編譯語言通常不實用,因為所有可能的執行中長度恆定的操作比一個特定程序執行中長度恆定的操作要少得
多。
此類優化的另一個重要的例子是基於類層次結構的優化。例如,一個虛方法調用需要查看接收方對象的類調用,以便找出哪個實際目標實現了接收方對象的虛方法。
研究表明:大多數虛調用只有一個目標對應於所有的接收方對象,而 JIT
編譯器可以為直接調用生成比虛調用更有效率的代碼。通過分析代碼編譯後類層次結構的狀態,JIT
編譯器可以為虛調用找到一個目標方法,並且生成直接調用目標方法的代碼而不是執行較慢的虛調用。當然,如果類層次結構發生變化,並且出現另外的目標方法,
則 JIT
編譯器可以更正最初生成的代碼以便執行虛調用。在實踐中,很少需要作出這些更正。另外,由於可能需要作出此類更正,因此靜態地執行這種優化非常麻煩。
因為動態編譯器通常只是集中編譯少量的熱方法,所以可以執行更主動的分析來生成更好的代碼,使編譯的回報更高。事實上,大部分現代的
JIT
編譯器也支持重編譯被認為是熱方法的方法。可以使用靜態編譯器(不太強調編譯時間)中常見的非常主動的優化來分析和轉換這些頻繁執行的方法,以便生成更好
的代碼並獲得更高的性能。
這些改進及其他一些類似的改進所產生的綜合效果是:對於大量的 Java 應用程序來說,動態編譯已經彌補了與 C 和 C++ 之類語言的靜態本地編譯性能之間的差距,在某些情況下,甚至超過了後者的性能。
缺點
但是,動態編譯確實具有一些缺點,這些缺點使它在某些情況下算不上一個理想的解決方案。例如,因為識別頻繁執行的方法以及編譯這些方法需要時間,所以應用
程序通常要經歷一個准備過程,在這個過程中性能無法達到其最高值。在這個准備過程中出現性能問題有幾個原因。首先,大量的初始編譯可能直接影響應用程序的
啟動時間。不僅這些編譯延遲了應用程序達到穩定狀態的時間(想像 Web
伺服器經
歷一個初始階段後才能夠執行實際有用的工作),而且在准備階段中頻繁執行的方法可能對應用程序的穩定狀態的性能所起的作用也不大。如果 JIT
編譯會延遲啟動又不能顯著改善應用程序的長期性能,則執行這種編譯就非常浪費。雖然所有的現代 JVM
都執行調優來減輕啟動延遲,但是並非在所有情況下都能夠完全解決這個問題。
其次,有些應用程序完全不能忍受動態編譯帶來的延遲。如 GUI 介面之類互動式應用程序就是這樣的例子。在這種情況下,編譯活動可能對用戶使用造成不利影響,同時又不能顯著地改善應用程序的性能。
最後,用於實時環境並具有嚴格的任務時限的應用程序可能無法忍受編譯的不確定性性能影響或動態編譯器本身的內存開銷。
因此,雖然 JIT 編譯技術已經能夠提供與靜態語言性能相當(甚至更好)的性能水平,但是動態編譯並不適合於某些應用程序。在這些情況下,Java 代碼的提前(Ahead-of-time,AOT)編譯可能是合適的解決方案。
AOT Java 編譯
大致說來,Java 語言本地編譯應該是為傳統語言(如 C++ 或
Fortran)而開發的編譯技術的一個簡單應用。不幸的是,Java 語言本身的動態特性帶來了額外的復雜性,影響了 Java
程序靜態編譯代碼的質量。但是基本思想仍然是相同的:在程序執行前生成 Java 方法的本地代碼,以便在程序運行時直接使用本地代碼。目的在於避免
JIT 編譯器的運行時性能消耗或內存消耗,或者避免解釋程序的早期性能開銷。
挑戰
動態類載入是動態 JIT 編譯器面臨的一個挑戰,也是 AOT
編譯的一個更重要的問題。只有在執行代碼引用類的時候才載入該類。因為是在程序執行前進行 AOT
編譯的,所以編譯器無法預測載入了哪些類。就是說編譯器無法獲知任何靜態欄位的地址、任何對象的任何實例欄位的偏移量或任何調用的實際目標,甚至對直接調
用(非虛調用)也是如此。在執行代碼時,如果證明對任何這類信息的預測是錯誤的,這意味著代碼是錯誤的並且還犧牲了 Java 的一致性。
因為代碼可以在任何環境中執行,所以類文件可能與代碼編譯時不同。例如,一個 JVM
實例可能從磁碟的某個特定位置載入類,而後面一個實例可能從不同的位置甚至網路載入該類。設想一個正在進行 bug
修復的開發環境:類文件的內容可能隨不同的應用程序的執行而變化。此外,Java 代碼可能在程序執行前根本不存在:比如 Java
反射服務通常在運行時生成新類來支持程序的行為。
缺少關於靜態、欄位、類和方法的信息意味著嚴重限制了 Java 編譯器中優化框架的大部分功能。內聯可能是靜態或動態編譯器應用的最重要的優化,但是由於編譯器無法獲知調用的目標方法,因此無法再使用這種優化。
內聯
內聯是一種用於在運行時生成代碼避免程序開始和結束時開銷的技術,方法是將函數的調用代碼插入到調用方的函數中。但是內聯最大的益處可能是優化方可見的代碼的范圍擴大了,從而能夠生成更高質量的代碼。下面是一個內聯前的代碼示例:
int foo() { int x=2, y=3; return bar(x,y); }final int bar(int a, int b) { return a+b; }
如果編譯器可以證明這個 bar就是 foo()中調用的那個方法,則 bar中的代碼可以取代 foo()中對
bar()的調用。這時,bar()方法是 final類型,因此肯定是 foo()中調用的那個方法。甚至在一些虛調用例子中,動態 JIT
編譯器通常能夠推測性地內聯目標方法的代碼,並且在絕大多數情況下能夠正確使用。編譯器將生成以下代碼:
int foo() { int x=2, y=3; return x+y; }
在這個例子中,簡化前名為值傳播的優化可以生成直接返回
5的代碼。如果不使用內聯,則不能執行這種優化,產生的性能就會低很多。如果沒有解析
bar()方法(例如靜態編譯),則不能執行這種優化,而代碼必須執行虛調用。運行時,實際調用的可能是另外一個執行兩個數字相乘而不是相加的
bar方法。所以不能在 Java 程序的靜態編譯期間直接使用內聯。
AOT
代碼因此必須在沒有解析每個靜態、欄位、類和方法引用的情況下生成。執行時,每個這些引用必須利用當前運行時環境的正確值進行更新。這個過程可能直接影響
第一次執行的性能,因為在第一次執行時將解析所有引用。當然,後續執行將從修補代碼中獲益,從而可以更直接地引用實例、靜態欄位或方法目標。
另外,為 Java 方法生成的本地代碼通常需要使用僅在單個 JVM 實例中使用的值。例如,代碼必須調用 JVM
運行時中的某些運行時常式來執行特定操作,如查找未解析的方法或分配內存。這些運行時常式的地址可能在每次將 JVM 載入到內存時變化。因此 AOT
編譯代碼需要綁定到 JVM 的當前執行環境中,然後才能執行。其他的例子有字元串的地址和常量池入口的內部位置。
在 WebSphere Real Time 中,AOT 本地代碼編譯通過 jxeinajar工具(參見圖 2)來執行。該工具對 JAR 文件中所有類的所有方法應用本地代碼編譯,也可以選擇性地對需要的方法應用本地代碼編譯。結果被存儲到名為 Java eXEcutable (JXE) 的內部格式中,但是也可輕松地存儲到任意的持久性容器中。
您可能認為對所有的代碼進行靜態編譯是最好的方法,因為可以在運行時執行最大數量的本地代碼。但是此處可以作出一些權衡。編譯的方法越多,代碼佔用的內存
就越多。編譯後的本地代碼大概比位元組碼大 10 倍:本地代碼本身的密度比位元組碼小,而且必須包含代碼的附加元數據,以便將代碼綁定到 JVM
中,並且在出現異常或請求堆棧跟蹤時正確執行代碼。構成普通 Java 應用程序的 JAR
文件通常包含許多很少執行的方法。編譯這些方法會消耗內存卻沒有什麼預期收益。相關的內存消耗包括以下過程:將代碼存儲到磁碟上、從磁碟取出代碼並裝入
JVM,以及將代碼綁定到 JVM。除非多次執行代碼,否則這些代價不能由本地代碼相對解釋的性能優勢來彌補。
圖 2. jxeinajar
跟大小問題相違背的一個事實是:在編譯過的方法和解釋過的方法之間進行的調用(即編譯過的方法調用解釋過的方法,或者相反)可能比這兩類方法各自內部之間
進行的調用所需的開銷大。動態編譯器通過最終編譯所有由 JIT
編譯代碼頻繁調用的那些解釋過的方法來減少這項開銷,但是如果不使用動態編譯器,則這項開銷就不可避免。因此如果是選擇性地編譯方法,則必須謹慎操作以使
從已編譯方法到未編譯方法的轉換最小化。為了在所有可能的執行中都避免這個問題而選擇正確的方法會非常困難。
優點
雖然 AOT 編譯代碼具有上述的缺點和挑戰,但是提前編譯 Java 程序可以提高性能,尤其是在不能將動態編譯器作為有效解決方案的環境中。
可以通過謹慎地使用 AOT 編譯代碼加快應用程序啟動,因為雖然這種代碼通常比 JIT
編譯代碼慢,但是卻比解釋代碼快很多倍。此外,因為載入和綁定 AOT
編譯代碼的時間通常比檢測和動態編譯一個重要方法的時間少,所以能夠在程序執行的早期達到那樣的性能。類似地,互動式應用程序可以很快地從本地代碼中獲
益,無需使用引起較差響應能力的動態編譯。
RT 應用程序也能從 AOT 編譯代碼中獲得重要的收益:更具確定性的性能超過了解釋的性能。WebSphere Real Time
使用的動態 JIT 編譯器針對在 RT 系統中的使用進行了專門的調整。使編譯線程以低於 RT
任務的優先順序操作,並且作出了調整以避免生成帶有嚴重的不確定性性能影響的代碼。但是,在一些 RT 環境中,出現 JIT
編譯器是不可接受的。此類環境通常需要最嚴格的時限管理控制。在這些例子中,AOT
編譯代碼可以提供比解釋過的代碼更好的原始性能,又不會影響現有的確定性。消除 JIT
編譯線程甚至消除了啟動更高優先順序 RT 任務時發生的線程搶占所帶來的性能影響。
優缺點統計
動態(JIT)編譯器支持平台中立性,並通過利用應用程序執行的動態行為和關於載入的類及其層次結構的信息來生成高質量的代碼。但是
JIT
編譯器具有一個有限的編譯時預算,而且會影響程序的運行時性能。另一方面,靜態(AOT)編譯器則犧牲了平台無關性和代碼質量,因為它們不能利用程序的動
態行為,也不具有關於載入的類或類層次結構的信息。AOT 編譯擁有有效無限制的編譯時預算,因為 AOT
編譯時間不會影響運行時性能,但是在實踐中開發人員不會長期等待靜態編譯步驟的完成。
表 1 總結了本文討論的 Java 語言動態和靜態編譯器的一些特性:
表 1. 比較編譯技術
兩種技術都需要謹慎選擇編譯的方法以實現最高的性能。對動態編譯器而言,編譯器自身作出決策,而對於靜態編譯器,由開發人員作出選擇。讓
JIT 編譯器選擇編譯的方法是不是優點很難說,取決於編譯器在給定情形中推斷能力的好壞。在大多數情況下,我們認為這是一種優點。
因為它們可以最好地優化運行中的程序,所以 JIT 編譯器在提供穩定狀態性能方面更勝一籌,而這一點在大量的生產 Java
系統中最為重要。靜態編譯可以產生最佳的互動式性能,因為沒有運行時編譯行為來影響用戶預期的響應時間。通過調整動態編譯器可以在某種程度上解決啟動和確
定性性能問題,但是靜態編譯在需要時可提供最快的啟動速度和最高級別的確定性。表 2 在四種不同的執行環境中對這兩種編譯技術進行了比較:
表 2. 使用這些技術的最佳環境
圖 3 展示了啟動性能和穩定狀態性能的總體趨勢:
圖 3. AOT 和 JIT 的性能對比
使用 JIT 編譯器的初始階段性能很低,因為要首先解釋方法。隨著編譯方法的增多及 JIT
執行編譯所需時間的縮短,性能曲線逐漸升高最後達到性能峰值。另一方面,AOT 編譯代碼啟動時的性能比解釋的性能高很多,但是無法達到 JIT
編譯器所能達到的最高性能。將靜態代碼綁定到 JVM 實例中會產生一些開銷,因此開始時的性能比穩定狀態的性能值低,但是能夠比使用 JIT
編譯器更快地達到穩定狀態的性能水平。
沒有一種本地代碼編譯技術能夠適合所有的 Java
執行環境。某種技術所擅長的通常正是其他技術的弱項。出於這個原因,需要同時使用這兩種編譯技術以滿足 Java
應用程序開發人員的要求。事實上,可以結合使用靜態和動態編譯以便提供最大可能的性能提升 —— 但是必須具備平台無關性,它是 Java
語言的主要賣點,因此不成問題。
結束語
本文探討了 Java 語言本地代碼編譯的問題,主要介紹了 JIT 編譯器形式的動態編譯和靜態 AOT 編譯,比較了二者的優缺點。
雖然動態編譯器在過去的十年裡實現了極大的成熟,使大量的各種 Java 應用程序可以趕上或超過靜態編譯語言(如 C++ 或
Fortran)所能夠達到的性能。但是動態編譯在某些類型的應用程序和執行環境中仍然不太合適。雖然 AOT
編譯號稱動態編譯缺點的萬能解決方案,但是由於 Java 語言本身的動態特性,它也面臨著提供本地編譯全部潛能的挑戰。
這兩種技術都不能解決 Java 執行環境中本地代碼編譯的所有需求,但是反過來又可以在最有效的地方作為工具使用。這兩種技術可以相互補充。能夠恰當地使用這兩種編譯模型的運行時系統可以使很大范圍內的應用程序開發環境中的開發人員和用戶受益。
③ atlas 鏄浠涔堢殑緙╁啓錛
C/ATLAS鍏ㄧОCommon / Abbreviated Test Language for All Systems(鍏ㄧ郴緇熷叕鍏/綆鏄庢祴璇曡璦)鏄涓涓騫挎硾鐢ㄤ簬鍐涗簨鍜岃埅絀烘祴璇曠殑鏍囧噯鍖栬璦.鐢盜EEE璐熻矗瀵硅ヨ璦鏍囧噯榪涜岀$悊緇存姢,璁稿氬浗瀹墮兘鍙傚姞浜嗚繖涓璇璦鐨勫紑鍙.鏈鏂囦粙緇嶇殑姝f槸鎴戝浗寮鍙戠殑ATLAS緙栬瘧鍣ㄤ腑鐨勮涔夊垎鏋愰儴鍒.
璇涔夊垎鏋愭槸緙栬瘧涓鐨勯噸鐐,鍦ㄨ涔夊垎鏋愪腑涓嶄粎瑕佽繘琛岀▼搴忕殑涓婁笅鏂囪涔変竴鑷存х殑媯鏌,榪樿佷負鐩鏍囦唬鐮佺敓鎴愭彁渚涜凍澶熺殑淇℃伅.鏈鏂囦粙緇嶄簡ATLAS璇涔夊垎鏋愮殑瀹炵幇鏂規硶,騫跺笰TLAS緋葷粺鐨勫疄鐜版妧鏈,榪愯岀幆澧冪殑瀹炵幇鏂規硶榪涜屼簡綆鍗曠殑浠嬬粛.
瀵逛簬ATLAS璇涔変腑瑕佹眰鐨勭壒孌婇棶棰,鎴戜滑閲囩敤浜嗛潰鍚戝硅薄鎶鏈鍔犱互瀹炵幇,騫跺彇寰椾簡寰堝ソ鐨勭粨鏋.鍏蜂綋鐨勫疄鐜伴噰鐢ㄩ潤鎬佽涔夊垎鏋愬拰鍔ㄦ佽涔夊垎鏋愮浉緇撳悎鐨勬柟娉.鏈鏂囧笰TLAS緋葷粺涓鐨勮懼囩$悊緋葷粺,榪愯岀幆澧冪郴緇熺瓑涔熻繘琛屼簡綆鍗曠殑浠嬬粛,涓篈TLAS緋葷粺鐨勮繘涓姝ュ紑鍙戝犲畾浜嗗熀紜.
鐩 褰
絎涓絝 緋葷粺綆浠
1.1 ATLAS 緋葷粺綆浠
C/ATLAS鏄鍏ㄧ郴緇熷叕鍏/綆鏄庢祴璇曡璦(Common / Abbreviated Test Language for All Systems)鐨勭緝鍐,瀹冩槸涓縐嶅姛鑳藉嶮鍒嗗己澶х殑鍏ㄧ郴緇熸爣鍑嗘祴璇曡璦,鍦ㄥ啗浜,鑸絀轟簨涓氫腑鍏鋒湁騫挎硾鐨勫簲鐢.
20涓栫邯60騫翠唬,ARINC鍏鍙鎬負浜嗗硅埅絀哄櫒涓婄殑鐢靛瓙璁懼囩郴緇熻繘琛屾祴璇,涓誨姙寮鍙戜簡涓涓嫻嬭瘯璇璦ATLAS,褰撴椂ATLAS鐨勫惈涔夋槸鎸嘇bbreviated Test Language for Avionics Systems .闅忓悗,緹庡浗闄嗗啗,嫻峰啗,鑸絀洪儴闃熶互鍙婂寳澶цタ媧嬪叕綰︾粍緇囦篃鍔犲叆鍒拌繖涓璇璦鐨勫紑鍙.
1976騫,C/ATLAS鐨勬帶鍒舵潈鐢盇RINC縐諱氦緇橧EEE,姝ゆ椂ATLAS鐨勫惈涔夋洿涓哄箍娉:Abbreviated Test Language for All Systems .鍚屾椂ARINC鍙戝竷浜咺EEE鏍煎紡鐨凙RINC416-13A鏍囧噯.1988騫,IEEE鍙戝竷浜咥TLAS716-1988/9鏍囧噯,鍚屽勾ARINC涔熷彂甯冧簡鏍囧噯ARINC626-1988/9,涔嬪悗IEEE鍜孉RINC姣忎笁,鍥涘勾灝辨洿鏂頒竴嬈″悇鑷鐨勬爣鍑.2000騫,IEEE鍙戝竷浜咰/ATLAS鐨勬渶鏂扮増鏈珹TLAS2000鏍囧噯,鎴戜滑瀹炵幇鐨勭郴緇熼噰鐢ㄧ殑灝辨槸IEEE鐨凙TLAS2000鏍囧噯.
C/ATLAS鍏鋒湁濡備笅鐨勭壒鐐:
涓,瀹冩槸涓涓鏍囧噯鐨勬祴璇曡璦.涓轟簡闃叉㈣璦鐨勬棩鐩婂簽澶у拰涓嶅埄浜庣淮鎶,璇ヨ璦鐢盜EEE璐熻矗鍙戝竷鐩稿簲鐨勬爣鍑,浠ヨ揪鍒拌璦鐨勮勮寖鍜岀粺涓.鍙備笌璇ユ爣鍑嗙殑涓昏佺敤鎴鋒湁緹庡浗鍥介槻閮,寰峰浗鍥介槻閮,娉曞浗鍥介槻閮,鑻卞浗鍥介槻閮,鐟炲吀鍥介槻閮ㄥ拰鑸絀哄伐涓氱殑鑸絀烘棤綰跨數鍏鍙哥瓑.
浜,C/ATLAS鍏鋒湁鍜屾祴璇曡懼囨棤鍏崇殑鐗規,鍙搴旂敤浜庢墍鏈夌殑嫻嬭瘯緋葷粺.鐢ˋTLAS璇璦緙栧啓鐨勭▼搴忓彲浠ユ祴璇曞悇縐嶄華鍣ㄨ懼,嫻嬭瘯鐨勪唬鐮佷腑涓嶅寘鎷浠諱綍嫻嬭瘯鎵閲囩敤鐨勭‖浠朵俊鎮.涔熷氨鏄璇,鍙瑕佹祴璇曚嬌鐢ㄧ殑鑷鍔ㄦ祴璇曡懼(ATE)鏀鎸丄TLAS,渚垮彲浠ヤ笉緇忚繃淇鏀瑰湴浣跨敤鍦ㄥ彟澶栦竴涓嫻嬭瘯緋葷粺涓緙栧啓鐨凙TLAS紼嬪簭.
涓,ATLAS鐨勫姛鑳藉嶮鍒嗗己澶,鎻愪緵浜嗙湡姝g殑鑷鍔ㄦ祴璇.鍦ㄤ互寰鐨勬祴璇曚腑,嫻嬭瘯浜哄憳涓嶄粎瑕佽冭檻嫻嬭瘯鐨勭畻娉曞拰嫻佺▼,榪樿佽姳寰堝氱簿鍔涚敤浜庨夋嫨嫻嬭瘯浣跨敤鐨勮懼囩敋鑷寵捐℃祴璇曟墍闇鐨勭‖浠剁瓑,榪涜屼笉鍚岀殑嫻嬭瘯闇瑕佷笉鍚岀殑嫻嬭瘯璁懼囧拰鐩稿簲鐨勬祴璇曟祦紼.鍦ˋTLAS涓鍒欎笉闇瑕佹祴璇曚漢鍛樿冭檻嫻嬭瘯紜浠,鑰岀敱ATLAS緋葷粺鑷鍔ㄥ勭悊,榪欐牱嫻嬭瘯浜哄憳灝辮兘澶熸洿鍔犱笓蹇冨湴榪涜屾祴璇曠畻娉曞拰嫻嬭瘯嫻佺▼璁捐.ATLAS緋葷粺鐨凙TE(鑷鍔ㄦ祴璇曡祫婧)涓鎻愪緵浜嗗ぇ閲忕殑嫻嬭瘯璁懼,涓涓獮TE鑳借繘琛屽緢澶氭祴璇,榪欐牱涓嶄粎綆鍖栦簡嫻嬭瘯緋葷粺鐨勮勬ā,涔熷ぇ澶ф彁楂樹簡嫻嬭瘯鐨勬晥鐜囧拰姘村鉤.
1.1.1 榪涜孉TLAS 嫻嬭瘯鐨勭‖浠剁幆澧
ATLAS璇璦鍙浠ュ簲鐢ㄤ簬鍚勭嶇數瀛愮被鍜岄潪鐢電被浠鍣ㄨ懼囩殑嫻嬭瘯,闅忕潃嫻嬭瘯鎶鏈鍜屾祴璇曡懼囩殑涓嶆柇鍙戝睍,ATLAS璇璦涔熷湪涓嶆柇鐨勮繘琛屼慨鏀.鍦ㄩ伒寰狪EEE鏍囧噯鐨勫熀紜涓,涓轟簡鏂逛究鐢ㄦ埛鐨勪嬌鐢,ATLAS璇璦鑷韜鎻愪緵浜嗕竴縐嶇殑鎵╁睍鏈哄埗,浠ュ畬鎴愮敱浜庡綋鍓嶆爣鍑嗙殑闄愬埗鑰屼笉鑳借繘琛岀殑嫻嬭瘯.
ATLAS 璇璦涓涓嶆彁渚涙祴璇曠‖浠朵俊鎮.鐢ㄦ埛浣跨敤榪囩▼涓,ATLAS緋葷粺鏍規嵁紼嬪簭涓鐨勮懼囩壒寰佷俊鎮,鑷鍔ㄥ湴榪涜岃懼囧垎閰嶅苟璋冪敤鐩稿簲鐨勭‖浠舵搷浣滄潵瀹屾垚瀵筓UT(琚嫻嬭瘯鍗曞厓)鐨勬祴璇.鍙浠ヨ碅TLAS緋葷粺鏄涓涓瀵規祴璇曡蔣浠跺拰紜浠惰繘琛岀$悊鐨勮櫄鎷熸満,瀹冧笉浠呰礋璐e笰TLAS婧愮▼搴忕紪璇,鐢熸垚鏈哄櫒鐮;榪樿佸規祴璇曡祫婧愯懼囪繘琛岀$悊,璁懼囩$悊鍖呮嫭:娣誨姞鍜屽垹闄よ懼,綆$悊琚嫻嬭瘯鍗曞厓(UUT)鍒拌嚜鍔ㄦ祴璇曠郴緇(ATE)璁懼囩殑寮鍏寵繛鎺ラ氳礬;姝ゅ,ATLAS緋葷粺榪樿佸湪嫻嬭瘯鐨勬墽琛岃繃紼嬩腑,澶勭悊嫻嬭瘯涓浜х敓鐨勪簨浠,騫剁洃鎺ф祴璇曡祫婧愮殑宸ヤ綔鎯呭喌.
涓嬪浘鏄疉TLAS嫻嬭瘯鐨勭‖浠剁幆澧.
,ATLAS嫻嬭瘯緋葷粺紜浠剁粨鏋勫浘
ATLAS嫻嬭瘯緋葷粺紜浠朵富瑕佹湁浠ヤ笅鍑犱釜閮ㄥ垎緇勬垚:
ATE(auto test equipment):鑷鍔ㄦ祴璇曡懼,浣挎暣涓嫻嬭瘯緋葷粺鐨勬牳蹇,閲囩敤VXI鎴朓EEE488 鎬葷嚎灝嗚懼囪繛鎺ュ埌涓繪満涓.ATE鏈烘煖涓鐨勮懼囦富瑕佸寘鎷:1)嫻嬭瘯浣跨敤鐨勮祫婧,濡傚悇縐嶅彲鎺х洿嫻佺數婧,鍙鎺т俊鍙峰彂鐢熷櫒,鏁板瓧涓囩敤琛,紺烘嘗鍣ㄧ瓑;2)寮鍏寵懼,鐢ㄤ簬榪炴帴ATE澶栭儴鐨勯樀鍒楁帴鍙e拰ATE鍐呴儴鐨勮懼.3)ATE闃靛垪鎺ュ彛,鏄疉TE鐨勮緭鍑烘帴鍙,澶栨帴嫻嬭瘯浣跨敤鐨勯傞厤鍣.
UUT(unit under test):琚嫻嬭瘯鍗曞厓,鍗蟲祴璇曠殑瀵硅薄,鍦ㄦ祴璇曡繃紼嬩腑鍜孉TE澶栭儴鐨勯傞厤鍣ㄧ浉榪炴帴.
閫傞厤鍣:鐢ㄤ簬榪炴帴ATE鍜孶UT.鍦ㄦ祴璇曡繃紼嬩腑,ATE璐熻矗鎻愪緵緇橴UT (琚嫻嬭瘯鍗曞厓)鐢墊簮,杈撳叆鐨勬縺鍔變俊鍙,騫朵粠UUT (琚嫻嬭瘯鍗曞厓)涓璇誨嚭嫻嬭瘯鐐圭殑鍐呭.閫傞厤鍣ㄧ殑浣滅敤灝辨槸榪涜屼粠ATE(鑷鍔ㄦ祴璇曡懼)鍒癠UT(琚嫻嬭瘯鍗曞厓)寤虹珛鐩稿簲鐨勮繛鎺,騫舵牴鎹甎UT 鎯呭喌榪涜岀數姘旇漿鎹,鐢典俊鍙峰埌闈炵數淇″彿鐨勮漿鎹㈢瓑.
VXI 鎬葷嚎絳:鐢ㄤ簬榪炴帴涓繪満鍜孉TE(鑷鍔ㄦ祴璇曡祫婧)涓鐨勬祴璇曡懼,鍙鎺у紑鍏崇瓑,榪涜孉TE鎺у埗鍜屾暟鎹閫氫俊.
涓繪満:嫻嬭瘯涓繪帶璁$畻鏈,鍏朵笂闈㈣繍琛孉TLAS緋葷粺.
1.1.2.ATLAS 緋葷粺緇撴瀯
ATLAS緋葷粺璐熻矗緙栬瘧鎵ц孉TLAS緙栧啓鐨勬祴璇曠▼搴,鎻愪緵璋冭瘯鐜澧,嫻嬭瘯浠跨湡鐜澧,綆$悊ATE涓鐨勫悇縐嶈懼囧拰寮鍏.ATLAS緋葷粺鐢盇TLAS緙栬瘧鍣,ATLAS榪愯岀幆澧,ATLAS鐜澧冪$悊紼嬪簭,璁懼囧簱,鎵╁睍鍗忚,鎬葷嚎鎻忚堪鏂囦歡,璁懼囨弿榪版枃浠,寮鍏蟲弿榪版枃浠跺拰閫傞厤鍣ㄦ弿榪版枃浠剁粍鎴.
緋葷粺鐨勭粨鏋勫備笅鍥炬墍紺:
ATLAS緋葷粺嫻嬭瘯嫻佺▼鍥
ATLAS 鐜澧冪$悊紼嬪簭灝嗘祴璇曚嬌鐢ㄧ殑璁懼囨弿榪版枃浠,寮鍏蟲弿榪版枃浠,鎬葷嚎鎻忚堪鏂囦歡鍜岄傞厤鍣ㄦ弿榪版枃浠惰漿鎹涓哄唴閮ㄧ殑璁懼囦俊鎮,寮鍏充俊鎮,鎬葷嚎淇℃伅鍜岄傞厤鍣ㄥ紩鑴氫俊鎮.
ATLAS緙栬瘧鍣ㄥ皢嫻嬭瘯紼嬪簭緙栬瘧鎴愬彲鎵ц岀殑鐩鏍囦唬鐮,騫朵氦緇橝TLAS榪愯岀郴緇熸墽琛.鍦ㄧ紪璇戠殑榪囩▼涓,ATLAS緙栬瘧鍣ㄦ牴鎹緋葷粺涓鐨勮懼囦俊鎮,寮鍏充俊鎮,鎬葷嚎鍜岄傞厤鍣ㄥ紩鑴氫俊鎮,榪涜屾祴璇曡懼囩殑鍒嗛厤,鐢熸垚鐩稿簲嫻嬭瘯璁懼囩殑鎿嶄綔浠g爜,騫跺湪嫻嬭瘯緇撴潫鍚庡洖鏀惰懼.
ATLAS榪愯岀郴緇熻礋璐f墽琛岀洰鏍囦唬鐮,瀹屾垚鏈緇堢殑嫻嬭瘯.鍦ㄨ繍琛岀郴緇熶腑瑕佺洃鎺ц懼囩殑鎵ц屾儏鍐,澶勭悊鏉ヨ嚜嫻嬭瘯璁懼囩殑淇″彿鍜屼腑鏂,綆$悊嫻嬭瘯鎵ц岀殑榪涚▼,騫剁粰紼嬪簭鍛樻彁渚涚浉搴旂殑璋冭瘯鐜澧.
鍦ㄦ墽琛屼腑,ATLAS鐨勮繍琛岀郴緇熻皟鐢ㄨ懼嘍LL搴撲腑鐨勮懼囧嚱鏁版潵鎵ц屾祴璇.璁懼囩$悊緋葷粺璐熻矗娣誨姞嫻嬭瘯璁懼,淇鏀瑰紑鍏抽氳礬,淇鏀規祴璇曡懼囦俊鎮,鍒犻櫎嫻嬭瘯璁懼囩瓑絳.娣誨姞鍜屼慨鏀逛竴涓璁懼囧垯鐩稿簲鐨勪慨鏀硅懼嘍LL搴.
ATLAS緙栬瘧鍣ㄦ牴鎹婧愮▼搴忎腑璁懼囩殑鐗瑰緛淇℃伅,緇撳悎緋葷粺鍐呴儴鐨勮懼囦俊鎮,寮曡剼淇℃伅鍜屽紑鍏充俊鎮,鏉ユ煡鎵捐懼.濡傛灉鎵懼埌婊¤凍鏉′歡鐨勮懼,鍒欏垎閰嶈ヨ懼囧苟璋冪敤榪欎釜璁懼囩殑鎿嶄綔.濡傛灉鏇存敼緋葷粺鐨勮懼,姣斿傛坊鍔犳柊璁懼囨垨淇鏀瑰綋鍓嶈懼囩殑鏌愪簺淇℃伅,榪欐椂瑕佷慨鏀圭郴緇熷唴閮ㄧ殑璁懼囦俊鎮,浠ヤ究鍦ˋTLAS緙栬瘧鏃惰兘澶熸壘鍒版弧瓚蟲潯浠剁殑璁懼.
1.2 鏈鏂囧畬鎴愮殑宸ヤ綔
鏈鏂囦粙緇嶇殑宸ヤ綔鏄鎴戜滑鐨勯」鐩鈥斺擜TLAS緋葷粺鐨勪竴閮ㄥ垎,涓昏佹槸ATLAS璇璦鐨勮涔夊垎鏋愰儴鍒,緇欏嚭浜咥TLAS褰㈠紡鍖栬涔,ATLAS緙栬瘧鐜澧,榪愯岀幆澧,ATLAS鐨勫姩鎬佽涔夊垎鏋愭妧鏈鍜岄潤鎬佽涔夊垎鏋愭妧鏈.鏈鏂囧畬鎴愮殑宸ヤ綔鏈:
瀹炵幇浜咥TLAS璇璦鐨勮涔夊垎鏋
鍒╃敤闈㈠悜瀵硅薄鐨勬妧鏈痆5][6]瑙e喅浜咥TLAS瑕佹眰鐨勮涔夋墿灞曞拰璁懼囨棤鍏蟲
闃愯堪浜咥TLAS緋葷粺鐨勭粍鎴愬拰鍚勯儴鍒嗙殑鍔熻兘
瀹炵幇浜咥TLAS鐨勮涔夊垎鏋愬櫒[7],緇欏嚭浜咥TLAS闈欐佽涔夋鏌ュ拰鍔ㄦ佽涔夋鏌ョ殑鍐呭,騫跺埄鐢ㄥ睘鎬ф枃娉曞姞浠ユ弿榪
絎浜岀珷 ATLAS璇璦
2.1 ATLAS 2000
ATLAS鏄涓涓鍗佸垎鏈夎叮鐨勮璦,涓庝竴鑸鐨勮繃紼嬪紡璇璦涓嶅悓,ATLAS鏇存帴榪戜簬鑷鐒惰璦.鍦ㄨ繖涓璇璦涓姣忎竴涓璇鍙ョ敱鍔ㄨ瘝,鍚嶈瘝鍜屽畠浠鐨勪慨楗頒俊鎮緇勬垚,涓涓獮TLAS璇鍙ヤ腑鑷沖皯鍖呭惈涓涓鍔ㄨ瘝鍜屼竴涓鍚嶈瘝[2].
ATLAS2000璇鍙ョ粨鏋勫備笅鍥炬墍紺:
鍥哄畾鍩 鍒嗛殧絎
,
鍥哄畾鍩熶腑鐨勬爣蹇楀煙,鐢ㄦ潵璇存槑榪欐潯璇鍙ョ殑鍚涔,濡傛灉蹇界暐鏍囧織璇存槑鏄涓鏉℃櫘閫氱殑璇鍙,鏄娉ㄩ噴璇鍙ュ垯鏍囧織涓"C" 鎴"B",濡傛灉鏄"E"琛ㄧず鍙浠ヤ粠鏍囧織鐨勮繖鏉¤鍙ュ紑濮嬫墽琛屾祴璇,鑰屼笌鍓嶉潰鐨勬祴璇曟棤鍏.
VERB鍔ㄨ瘝,鍖呮嫭ATLAS涓鐨勫姩璇嶅拰鍔ㄨ瘝淇楗拌瘝.鍔ㄨ瘝鏈:APPLY,DEFINE,DECLARE,REQUIRE,DISCONNECT,REMOVE,DO絳.鍔ㄨ瘝鐨勪慨楗拌瘝鐢ㄦ潵杈呭姪鍔ㄨ瘝濡:"DO ,SIMULTANEOUS" 璇鍙ヤ腑鐨凷IMULANEOUS,淇″彿璇鍙ヤ腑鐨"THEN RESET"絳.
鍒嗛殧絎,鍦ˋTLAS涓涓嶅悓鐨勮娉曟垚鍒嗙敱鍒嗛殧絎","闅斿紑.
姣忎竴鏉¢兘鏈変竴涓緇堟㈢"$".
姣忎釜璇鍙ョ殑璇鍙ュ墿浣欓儴鍒嗘牴鎹鎯呭喌鑰屽畾.
ATLAS2000緇撴瀯:
ATLAS2000 鏄涓涓鏈夊氬眰緇撴瀯鐨勮璦[4],涓涓獮TLAS紼嬪簭鐢辨牳瀛愬師璇,璇鍙,妯″瀷,TTF鍜屾ā鍧楃粍鎴.ATLAS鏍稿瓙閮ㄥ垎鍜孉TLAS鍘熻鏋勬垚浜嗚繖涓璇璦鐨勫熀紜,鐢ㄦ埛閫氳繃棰勫畾涔夊拰榪欎簺鍩烘湰璇緔犳潵寤虹珛嫻嬭瘯欏圭洰鐨勯渶奼.妯″瀷緇撴瀯浣跨敤鎴烽氳繃瀵瑰簳灞傞儴浠剁殑鎿嶄綔緇勫悎,鎶借薄鍑哄叿鏈夋洿楂樺眰嬈$殑緇撴瀯騫跺規洿澶嶆潅鐨勬祴璇曞姛鑳藉姞浠ユ弿榪.TTF(Test Technology Frameworks)嫻嬭瘯鎶鏈妗嗘灦,ATLAS2000嫻嬭瘯鎶鏈妗嗘灦鍖呮嫭騫跺畾涔変竴浜涚敱ATLAS2000鍩虹緇勬垚鐨勭壒孌婄殑嫻嬭瘯鐜澧.妯″潡鐢ㄦ潵灝佽呴偅浜涘彲閲嶅嶄嬌鐢ㄧ殑嫻嬭瘯浠g爜.鍏蜂綋緇撴瀯濡備笅鍥炬墍紺:
ATLAS 2000 緇撴瀯鍥
娉ㄩ噴:
ATLAS鏍稿瓙閮ㄥ垎(NUCLEUS)瀹氫箟浜咥TLAS璇璦鍏稿瀷鐨勬ц兘鍜屽姛鑳.ATLAS鏍稿瓙鐢卞艦寮忚娉,淇濈暀瀛楀拰瑙勫垯涓変釜閮ㄥ垎緇勬垚.
ATLAS鍘熻(PRIMITIVES)鏄鎻忚堪鍜岃存槑ATLAS淇″彿,鍔ㄤ綔,灞炴у拰鎬ц兘蹇呴渶鐨勫厓緔.榪欎簺鍩烘湰鍏冪礌涓嶈兘鍐嶅垎,鍏朵腑鍖呮嫭鍚嶈瘝,鍚嶈瘝淇楗拌瘝,鍔ㄨ瘝,鍔ㄨ瘝淇楗拌瘝,鎿嶄綔絎︿互鍙婂畠浠鐨勫姛鑳藉畾涔.
ATLAS妯″瀷(MODELS)鏄涓緋誨垪鍑芥暟鍜岃繃紼嬬殑琛ㄧず,鍦ˋTLAS涓,妯″瀷鐢ㄦ潵鎻忚堪嫻嬭瘯璁懼囧拰琚嫻嬭瘯鍗曞厓(UUT)鐨勭壒寰.ATLAS妯″瀷鏄鏂囨硶鍏冪礌鐨勬弿榪板熀紜,ATLAS鍏抽敭瀛楁牴鎹瓵TLAS2000妯″瀷鏉ュ畾涔,鎵鏈夌殑鍏抽敭瀛楀繀欏繪ā鍨嬪寲.涓鏃︿竴涓妯″瀷琚瀹氫箟騫朵笖鎴愪負嫻嬭瘯鎶鏈妗嗘灦(TTF)鐨勪竴閮ㄥ垎,灝卞彲浠ュ湪ATLAS鐨勮鍙ヤ腑浣滀負涓涓鍏抽敭瀛楁潵浣跨敤.
ATLAS鐨勬ā鍧(MODULE)鏄鍖呭惈鍦ˋTLAS紼嬪簭涓鐨勪竴涓瀹炰綋,鍙浠ヨ村畠鏄涓涓鍖呭惈ATLAS榪囩▼鍜岄潪ATLAS榪囩▼鐨勫瑰櫒.鍦ˋTLAS涓鐢"INCLUDE"璇鍙ユ潵浣跨敤妯″潡.鍦ㄦā鍧楀唴閫氳繃澹版槑榪囩▼鐨勫睘鎬ф槸鍏ㄥ矓鐨勮繕鏄灞閮ㄧ殑,鏉ュ喅瀹氳繃紼嬬殑浣滅敤鍩,鍏ㄥ矓鐨勮繃紼嬪彲浠ュ湪妯″潡澶栦嬌鐢.鍦ㄦā鍧楀唴閮ㄥ彲浣跨敤鏈妯″潡瀹氫箟鐨勬墍鏈夎繃紼,閫氳繃瀵瑰叾瀹冪殑妯″潡榪涜屽紩鐢ㄥ0鏄,涔熷彲浣跨敤澶栭儴榪囩▼.
2.2 ATLAS 璇涔夊垎鏋愮壒鐐
ATLAS璇璦鏄鐢ㄤ簬嫻嬭瘯鐨勬爣鍑嗚璦.灝界″湪ATLAS璇璦涓娌℃湁鍏充簬嫻嬭瘯璁懼囩‖浠剁殑鍏蜂綋淇℃伅,濡傝懼囩殑鐗╃悊鍦板潃,璁懼囬┍鍔ㄧ▼搴忓拰璁懼囩殑鎿嶄綔鍑芥暟絳,浣嗘槸ATLAS鎻愪緵浜嗘弿榪拌懼囩壒寰佺殑鍘熻鍜屾ā鍨媅1][3],鍏朵腑鍖呮嫭:鍚嶈瘝,鍔ㄨ瘝,淇楗拌瘝,榪炴帴鍜屼俊鍙蜂繚鐣欏瓧絳.ATLAS緙栬瘧鍣ㄦf槸鏍規嵁鍦ˋTLAS紼嬪簭涓鐨勭敱榪欎簺鍘熻鍜屾ā鍨嬬粍鎴愮殑淇℃伅,鏉ヨ嚜鍔ㄥ湴瀹屾垚璁懼囨煡鎵,璁懼囧垎閰,鍘婚厤鍜屾搷浣.
鍜屽父瑙佺殑紼嬪簭璇璦鐩告瘮,ATLAS鏈澶х殑鐗圭偣灝辨槸鍖呮嫭浜嗕竴浜涗笌嫻嬭瘯璁懼囨垨琚嫻嬪崟鍏冪浉鍏崇殑淇℃伅鍜岃鍙[1],鑰屽規祴璇曡懼囪繘琛屾搷浣滀篃灝辨槸ATLAS璇涔夌殑閲嶈侀儴鍒.鐜板湪鎴戜滑鏉ュ規瘮涓涓闈濧TLAS璇璦鍜孉TLAS璇璦鏄濡備綍緙栧啓嫻嬭瘯紼嬪簭鐨.
鎴戜滑浠嶤璇璦鐨勬祴璇曠▼搴忓拰ATLAS璇璦緙栧啓鐨勫悓鏍峰姛鑳界殑紼嬪簭榪涜屼竴涓嬪規瘮.
渚:灝嗕竴涓鐢靛帇鏄28v鐨勭洿嫻佺數婧愯繛鎺ュ埌琚嫻嬭瘯璁懼(UUT)涓.
瀹炵幇:
鐢–璇璦緙栧啓嫻嬭瘯紼嬪簭鐨勫叿浣撴搷浣滄ラゆ槸:棣栧厛灝嗚佷嬌鐢ㄧ殑鐢墊簮榪炴帴鍒版祴璇曠郴緇熶笂,灝嗙數婧愬埌UUT鐨勫紑鍏崇疆涓鴻繛鎺,鐒跺悗璁劇疆鐢墊簮鐢靛帇涓28V,鎺ヤ笅鏉ユ鏌ョ數婧愮殑杈撳嚭鐢靛帇鏄鍚︽槸28V,宸ヤ綔鐢墊祦鏄鍚﹀皬浜1A,濡傛灉婊¤凍鏉′歡鍒欏厑璁歌ョ數婧愬伐浣.
鍦ˋTLAS涓,閫氳繃涓鏉$畝鍗曠殑璇鍙ュ氨鍙浠ュ畬鎴愪簡榪欎簺鎿嶄綔,鍦ˋTLAS紼嬪簭涓涓嶉渶瑕佹寚鍑鴻佷嬌鐢ㄥ摢涓涓鐢墊簮,鎴戜滑鍙浠ョ湅鍑篈TLAS鍜孋璇璦鐨勪笉鍚屼箣澶.鍦–鐨勭▼搴忎腑鐢辨祴璇曞憳鎸囧畾瑕佷嬌鐢ㄧ殑鐢墊簮騫惰繛鎺ヨ繖涓鐢墊簮鐨勪嬌鐢ㄧ殑寮鍏寵繖鏍鋒潵瀹屾垚嫻嬭瘯,鍦ˋTLAS榪欎簺宸ヤ綔涓鍒欑敱緙栬瘧鍣ㄨ嚜鍔ㄥ畬鎴.
C璇璦鍜孉TLAS璇璦緙栧啓鐨勪唬鐮佹瘮杈冨備笅:
鎽樿嚜錛歴oftlab.jlu.e.cn/temp/thesis/2004liulei.doc
④ 編程怎麼做怎麼編代碼java 我不會
1.如何學習程序設計?
JAVA是一種平台,也是一種程序設計語言,如何學好程序設計不僅僅適用於JAVA,對C++等其他程序設計語言也一樣管用。有編程高手認為,JAVA也好C也好沒什麼分別,拿來就用。為什麼他們能達到如此境界?我想是因為編程語言之間有共通之處,領會了編程的精髓,自然能夠做到一通百通。如何學習程序設計理所當然也有許多共通的地方。1 培養興趣 2 慎選程序設計語言 3 要腳踏實地,快餐式的學習不可取 4 多實踐,快實踐5 多參考程序代碼
6 加強英文閱讀能力 7 萬不得已才請教別人8 多讀好書
9 使用合適的工具 學習JAVAJAVA學習路線
1 基礎語法及JAVA原理
基礎語法和JAVA原理是地基,地基不牢靠,猶如沙地上建摩天大廈,是相當危險的。學習JAVA也是如此,必須要有扎實的基礎,你才能在J2EE、J2ME領域游刃有餘。參加SCJP(SUN公司認證的JAVA程序員)考試不失為一個好方法,原因之一是為了對得起你交的1200大洋考試費,你會更努力學習,原因之二是SCJP考試能夠讓你把基礎打得很牢靠,它要求你跟JDK一樣熟悉JAVA基礎知識;但是你千萬不要認為考過了SCJP就有多了不起,就能夠獲得軟體公司的青睞,就能夠獲取高薪,這樣的想法也是很危險的。獲得"真正"的SCJP只能證明你的基礎還過得去,但離實際開發還有很長的一段路要走。
2 OO思想的領悟
掌握了基礎語法和JAVA程序運行原理後,我們就可以用JAVA語言實現面向對象的思想了。面向對象,是一種方法學;是獨立於語言之外的編程思想;是CBD基於組件開發的基礎;屬於強勢技術之一。當以後因工作需要轉到別的面向對象語言的時候,你會感到特別的熟悉親切,學起來像喝涼水這么簡單。
使用面向對象的思想進行開發的基本過程是:
●調查收集需求。
●建立用例模型。
●從用例模型中識別分析類及類與類之間的靜態動態關系,從而建立分析模型。
●細化分析模型到設計模型。
●用具體的技術去實現。
●測試、部署、總結。
3 基本API的學習
進行軟體開發的時候,並不是什麼功能都需要我們去實現,也就是經典名言所說的"不需要重新發明輪子"。我們可以利用現成的類、組件、框架來搭建我們的應用,如SUN公司編寫好了眾多類實現一些底層功能,以及我們下載過來的JAR文件中包含的類,我們可以調用類中的方法來完成某些功能或繼承它。那麼這些類中究竟提供了哪些方法給我們使用?方法的參數個數及類型是?類的構造器需不需要參數?總不可能SUN公司的工程師打國際長途甚至飄洋過海來告訴你他編寫的類該如何使用吧。他們只能提供文檔給我們查看,JAVADOC文檔(參考文獻4.4)就是這樣的文檔,它可以說是程序員與程序員交流的文檔。
基本API指的是實現了一些底層功能的類,通用性較強的API,如字元串處理/輸入輸出等等。我們又把它成為類庫。熟悉API的方法一是多查JAVADOC文檔(參考文獻4.4),二是使用JBuilder/Eclipse等IDE的代碼提示功能4 特定API的學習
JAVA介入的領域很廣泛,不同的領域有不同的API,沒有人熟悉所有的API,對一般人而言只是熟悉工作中要用到的API。如果你做界面開發,那麼你需要學習Swing/AWT/SWT等API;如果你進行網路游戲開發,你需要深入了解網路API/多媒體API/2D3D等;如果你做WEB開發,就需要熟悉Servlet等API啦。總之,需要根據工作的需要或你的興趣發展方向去選擇學習特定的API。
5 開發工具的用法
在學習基礎語法與基本的面向對象概念時,從鍛煉語言熟練程度的角度考慮,我們推薦使用的工具是Editplus/JCreator+JDK,這時候不要急於上手JBuilder/Eclipse等集成開發環境,以免過於關注IDE的強大功能而分散對JAVA技術本身的注意力。過了這一階段你就可以開始熟悉IDE了。
程序員日常工作包括很多活動,編輯、編譯及構建、調試、單元測試、版本控制、維持模型與代碼同步、文檔的更新等等,幾乎每一項活動都有專門的工具,如果獨立使用這些工具的話,你將會很痛苦,你需要在堆滿工具的任務欄上不斷的切換,效率很低下,也很容易出錯。在JBuilder、Eclipse等IDE中已經自動集成編輯器、編譯器、調試器、單元測試工具JUnit、自動構建工具ANT、版本控制工具CVS、DOC文檔生成與更新等等,甚至可以把UML建模工具也集成進去,又提供了豐富的向導幫助生成框架代碼,讓我們的開發變得更輕松。應該說IDE發展的趨勢就是集成軟體開發中要用到的幾乎所有工具。
從開發效率的角度考慮,使用IDE是必經之路,也是從一個學生到一個職業程序員轉變的里程碑。
JAVA開發使用的IDE主要有Eclipse、JBuilder、JDeveloper、NetBeans等幾種;而Eclipse、JBuilder佔有的市場份額是最大的。JBuilder在近幾年來一直是JAVA集成開發環境中的霸主,它是由備受程序員尊敬的Borland公司開發,在硝煙彌漫的JAVAIDE大戰中,以其快速的版本更新擊敗IBM的VisualAgeforJAVA等而成就一番偉業。IBM在VisualAgeforJAVA上已經無利可圖之下,乾脆將之貢獻給開源社區,成為Eclipse的前身,真所謂"柳暗花明又一村"。浴火重生的Eclipse以其開放式的插件擴展機制、免費開源獲得廣大程序員(包括幾乎所有的骨灰級程序員)的青睞,極具發展潛力。
6 學習軟體工程
對小型項目而言,你可能認為軟體工程沒太大的必要。隨著項目的復雜性越來越高,軟體工程的必要性才會體現出來。參見"軟體開發學習路線"小節。
7 學習要點
確立的學習路線之後,我們還需要總結一下JAVA的學習要點,這些要點在前文多多少少提到過,只是筆者覺得這些地方特別要注意才對它們進行匯總,不要嫌我婆婆媽媽啊。
8 勤查API文檔
當程序員編寫好某些類,覺得很有成就感,想把它貢獻給各位苦難的同行。這時候你要使用"javadoc"工具(包含在JDK中)生成標準的JAVADOC文檔,供同行使用。J2SE/J2EE/J2ME的DOC文檔是程序員與程序員交流的工具,幾乎人手一份,除了菜鳥之外。J2SEDOC文檔官方下載地址: http://java.sun.com/j2se/1.5.0/download.jsp,你可以到google搜索CHM版本下載。也可以在線查看: http://java.sun.com/j2se/1.5.0/docs/api/index.html。
對待DOC文檔要像毛主席語錄,早上起床念一遍,吃飯睡覺前念一遍。
當需要某項功能的時候,你應該先查相應的DOC文檔看看有沒有現成的實現,有的話就不必勞神費心了直接用就可以了,找不到的時候才考慮自己實現。使用步驟一般如下:
●找特定的包,包一般根據功能組織。
●找需要使用類,類命名規范的話我們由類的名字可猜出一二。
●選擇構造器,大多數使用類的方式是創建對象。
●選擇你需要的方法。
9 查書/google->寫代碼測試->查看源代碼->請教別人
當我們遇到問題的時候該如何解決?
這時候不要急著問別人,太簡單的問題,沒經過思考的問題,別人會因此而瞧不起你。可以先找找書,到google中搜一下看看,絕大部分問題基本就解決了。而像"某些類/方法如何使用的問題",DOC文檔就是答案。對某些知識點有疑惑是,寫代碼測試一下,會給你留下深刻的印象。而有的問題,你可能需要直接看API的源代碼驗證你的想法。萬不得已才去請教別人。
10學習開源軟體的設計思想
JAVA領域有許多源代碼開放的工具、組件、框架,JUnit、ANT、Tomcat、Struts、Spring、Jive論壇、PetStore寵物店等等多如牛毛。這些可是前輩給我們留下的瑰寶呀。入寶山而空手歸,你心甘嗎?對這些工具、框架進行分析,領會其中的設計思想,有朝一日說不定你也能寫一個XXX框架什麼的,風光一把。分析開源軟體其實是你提高技術、提高實戰能力的便捷方法。
11規范的重要性
沒有規矩,不成方圓。這里的規范有兩層含義。第一層含義是技術規范,多到 http://www.jcp.org下載JSRXXX規范,多讀規范,這是最權威准確最新的教材。第二層含義是編程規范,如果你使用了大量的獨特演算法,富有個性的變數及方法的命名方式;同時,沒給程序作注釋,以顯示你的編程功底是多麼的深厚。這樣的代碼別人看起來像天書,要理解談何容易,更不用說維護了,必然會被無情地掃入垃圾堆。JAVA編碼規范到此查看或下載 http://java.sun.com/docs/codeconv/,中文的也有,啊,還要問我在哪,請參考3.2.2節。
12 不局限於JAVA
很不幸,很幸運,要學習的東西還有很多。不幸的是因為要學的東西太多且多變,沒時間陪老婆家人或女朋友,導致身心疲憊,嚴重者甚至導致抑鬱症。幸運的是別人要搶你飯碗絕非易事,他們或她們需要付出很多才能達成心願。
JAVA不要孤立地去學習,需要綜合學習數據結構、OOP、軟體工程、UML、網路編程、資料庫技術等知識,用橫向縱向的比較聯想的方式去學習會更有效。如學習JAVA集合的時候找數據結構的書看看;學JDBC的時候復習資料庫技術;採取的依然是"需要的時候再學"的原則。
⑤ 誰能簡單闡述下java編譯執行的過程
Java虛擬機(JVM)是可運行Java代碼的假想計算機。只要根據JVM規格描述將解釋器移植到特定的計算機上,就能保證經過編譯的任何Java代碼能夠在該系統上運行。本文首先簡要介紹從Java文件的編譯到最終執行的過程,隨後對JVM規格描述作一說明。
一.Java源文件的編譯、下載、解釋和執行
Java應用程序的開發周期包括編譯、下載、解釋和執行幾個部分。Java編譯程序將Java源程序翻譯為JVM可執行代碼?位元組碼。這一編譯過程同C/C++的編譯有些不同。當C編譯器編譯生成一個對象的代碼時,該代碼是為在某一特定硬體平台運行而產生的。因此,在編譯過程中,編譯程序通過查表將所有對符號的引用轉換為特定的內存偏移量,以保證程序運行。Java編譯器卻不將對變數和方法的引用編譯為數值引用,也不確定程序執行過程中的內存布局,而是將這些符號引用信息保留在位元組碼中,由解釋器在運行過程中創立內存布局,然後再通過查表來確定一個方法所在的地址。這樣就有效的保證了Java的可移植性和安全性。
運行JVM位元組碼的工作是由解釋器來完成的。解釋執行過程分三部進行:代碼的裝入、代碼的校驗和代碼的執行。裝入代碼的工作由"類裝載器"(class loader)完成。類裝載器負責裝入運行一個程序需要的所有代碼,這也包括程序代碼中的類所繼承的類和被其調用的類。當類裝載器裝入一個類時,該類被放在自己的名字空間中。除了通過符號引用自己名字空間以外的類,類之間沒有其他辦法可以影響其他類。在本台計算機上的所有類都在同一地址空間內,而所有從外部引進的類,都有一個自己獨立的名字空間。這使得本地類通過共享相同的名字空間獲得較高的運行效率,同時又保證它們與從外部引進的類不會相互影響。當裝入了運行程序需要的所有類後,解釋器便可確定整個可執行程序的內存布局。解釋器為符號引用同特定的地址空間建立對應關系及查詢表。通過在這一階段確定代碼的內存布局,Java很好地解決了由超類改變而使子類崩潰的問題,同時也防止了代碼對地址的非法訪問。
隨後,被裝入的代碼由位元組碼校驗器進行檢查。校驗器可發現操作數棧溢出,非法數據類型轉化等多種錯誤。通過校驗後,代碼便開始執行了。
Java位元組碼的執行有兩種方式:
1.即時編譯方式:解釋器先將位元組碼編譯成機器碼,然後再執行該機器碼。
2.解釋執行方式:解釋器通過每次解釋並執行一小段代碼來完成Java位元組碼程 序的所有操作。
通常採用的是第二種方法。由於JVM規格描述具有足夠的靈活性,這使得將位元組碼翻譯為機器代碼的工作
具有較高的效率。對於那些對運行速度要求較高的應用程序,解釋器可將Java位元組碼即時編譯為機器碼,從而很好地保證了Java代碼的可移植性和高性能。
二.JVM規格描述
JVM的設計目標是提供一個基於抽象規格描述的計算機模型,為解釋程序開發人員提很好的靈活性,同時也確保Java代碼可在符合該規范的任何系統上運行。JVM對其實現的某些方面給出了具體的定義,特別是對Java可執行代碼,即位元組碼(Bytecode)的格式給出了明確的規格。這一規格包括操作碼和操作數的語法和數值、標識符的數值表示方式、以及Java類文件中的Java對象、常量緩沖池在JVM的存儲映象。這些定義為JVM解釋器開發人員提供了所需的信息和開發環境。Java的設計者希望給開發人員以隨心所欲使用Java的自由。
JVM定義了控制Java代碼解釋執行和具體實現的五種規格,它們是:
JVM指令系統
JVM寄存器
JVM棧結構
JVM碎片回收堆
JVM存儲區
2.1JVM指令系統
JVM指令系統同其他計算機的指令系統極其相似。Java指令也是由 操作碼和操作數兩部分組成。操作碼為8位二進制數,操作數進緊隨在操作碼的後面,其長度根據需要而不同。操作碼用於指定一條指令操作的性質(在這里我們採用匯編符號的形式進行說明),如iload表示從存儲器中裝入一個整數,anewarray表示為一個新數組分配空間,iand表示兩個整數的"與",ret用於流程式控制制,表示從對某一方法的調用中返回。當長度大於8位時,操作數被分為兩個以上位元組存放。JVM採用了"big endian"的編碼方式來處理這種情況,即高位bits存放在低位元組中。這同 Motorola及其他的RISC CPU採用的編碼方式是一致的,而與Intel採用的"little endian "的編碼方式即低位bits存放在低位位元組的方法不同。
Java指令系統是以Java語言的實現為目的設計的,其中包含了用於調用方法和監視多先程系統的指令。Java的8位操作碼的長度使得JVM最多有256種指令,目前已使用了160多種操作碼。
2.2JVM指令系統
所有的CPU均包含用於保存系統狀態和處理器所需信息的寄存器組。如果虛擬機定義較多的寄存器,便可以從中得到更多的信息而不必對棧或內存進行訪問,這有利於提高運行速度。然而,如果虛擬機中的寄存器比實際CPU的寄存器多,在實現虛擬機時就會佔用處理器大量的時間來用常規存儲器模擬寄存器,這反而會降低虛擬機的效率。針對這種情況,JVM只設置了4個最為常用的寄存器。它們是:
pc程序計數器
optop操作數棧頂指針
frame當前執行環境指針
vars指向當前執行環境中第一個局部變數的指針
所有寄存器均為32位。pc用於記錄程序的執行。optop,frame和vars用於記錄指向Java棧區的指針。
2.3JVM棧結構
作為基於棧結構的計算機,Java棧是JVM存儲信息的主要方法。當JVM得到一個Java位元組碼應用程序後,便為該代碼中一個類的每一個方法創建一個棧框架,以保存該方法的狀態信息。每個棧框架包括以下三類信息:
局部變數
執行環境
操作數棧
局部變數用於存儲一個類的方法中所用到的局部變數。vars寄存器指向該變數表中的第一個局部變數。
執行環境用於保存解釋器對Java位元組碼進行解釋過程中所需的信息。它們是:上次調用的方法、局部變數指針和操作數棧的棧頂和棧底指針。執行環境是一個執行一個方法的控制中心。例如:如果解釋器要執行iadd(整數加法),首先要從frame寄存器中找到當前執行環境,而後便從執行環境中找到操作數棧,從棧頂彈出兩個整數進行加法運算,最後將結果壓入棧頂。
操作數棧用於存儲運算所需操作數及運算的結果。
2.4JVM碎片回收堆
Java類的實例所需的存儲空間是在堆上分配的。解釋器具體承擔為類實例分配空間的工作。解釋器在為一個實例分配完存儲空間後,便開始記錄對該實例所佔用的內存區域的使用。一旦對象使用完畢,便將其回收到堆中。
在Java語言中,除了new語句外沒有其他方法為一對象申請和釋放內存。對內存進行釋放和回收的工作是由Java運行系統承擔的。這允許Java運行系統的設計者自己決定碎片回收的方法。在SUN公司開發的Java解釋器和Hot Java環境中,碎片回收用後台線程的方式來執行。這不但為運行系統提供了良好的性能,而且使程序設計人員擺脫了自己控制內存使用的風險。
2.5JVM存儲區
JVM有兩類存儲區:常量緩沖池和方法區。常量緩沖池用於存儲類名稱、方法和欄位名稱以及串常量。方法區則用於存儲Java方法的位元組碼。對於這兩種存儲區域具體實現方式在JVM規格中沒有明確規定。這使得Java應用程序的存儲布局必須在運行過程中確定,依賴於具體平台的實現方式。
JVM是為Java位元組碼定義的一種獨立於具體平台的規格描述,是Java平台獨立性的基礎。目前的JVM還存在一些限制和不足,有待於進一步的完善,但無論如何,JVM的思想是成功的。
對比分析:如果把Java原程序想像成我們的C++原程序,Java原程序編譯後生成的位元組碼就相當於C++原程序編譯後的80x86的機器碼(二進製程序文件),JVM虛擬機相當於80x86計算機系統,Java解釋器相當於80x86CPU。在80x86CPU上運行的是機器碼,在Java解釋器上運行的是Java位元組碼。
Java解釋器相當於運行Java位元組碼的「CPU」,但該「CPU」不是通過硬體實現的,而是用軟體實現的。Java解釋器實際上就是特定的平台下的一個應用程序。只要實現了特定平台下的解釋器程序,Java位元組碼就能通過解釋器程序在該平台下運行,這是Java跨平台的根本。當前,並不是在所有的平台下都有相應Java解釋器程序,這也是Java並不能在所有的平台下都能運行的原因,它只能在已實現了Java解釋器程序的平台下運行。
⑥ 有哪些體系結構模式
一、體系結構定義:
體系結構是一個計算機術語,由G. Amdahl於1964年首次提出體系結構概念,為以後計算機系統的設計與開發奠定了良好的基礎。體系結構包括數據流系統、調用-返回系統、獨立部件、虛擬機、以數據為中心的系統(庫)、特殊領域風格、特殊結構風格、不同風格合成建立的異構結構、最初始最基本的主程序/子程序九大內容。
二、體系結構由來:
在傳統的程序設計領域中,人們使用流程圖來表達系統的基本功能和實現的具體邏輯,但是,流程圖實際上僅僅是源程序的圖形化表示,無法給系統的分析和開發者提供更多的信息,所以沒有在實際的系統開發過程中得到廣泛的應用。隨著軟體系統的規模和復雜性的增加,對軟體系統的整體結構(數據和控制的邏輯)進行分析和描述成為大型系統開發的一個不可缺少的重要部分,顯然,使用流程圖是無法達到這個目標的,我們必須使用新的方法和概念來對系統的整體結構進行把握。
三、體系結構的分類:
1.數據流系統,包括順序批處理、管道和過濾器;
2. 調用-返回系統,包括主程序和子程序、面向對象系統、層次結構;
3. 獨立部件,包括通信進程、事件隱式調用;
4.虛擬機,包括解釋器、規則基系統;
5. 以數據為中心的系統(庫),包括資料庫、超文本系統、黑板系統;
6. 特殊領域風格;例如過程式控制制、模擬器;
7. 特殊結構的風格,例如分布式處理、狀態轉移系統;
8. 不同風格合成建立的異構結構;
9. 最初始、最基本的主程序/子程序。
四、結構範式:
1.管道和過濾器
每個組件具有輸入和輸出的集合,從流中讀出數據作為輸入,產生輸出數據的流。整個系統可以看成多個過濾器復合形成的數據處理組件。
過濾器A
過濾器B
過濾器C
管道
特點:
過濾器之間是相互獨立的(不能共享狀態),其中一個過濾器的操作和行為不能影響另外過濾器的操作和行為,流的傳送沒有副作用。
過濾器對所輸入流的來源和輸出流的去向不關心,不需要知道流的來源和流的去向,來源和去向對於過濾器的數據處理沒有任何影響。
過濾和流的傳送可以是並發的,可以同時有多個流的傳送存在於系統之中。
實例:
一個最著名的實例是unix的shell編程,多個對數據進行處理的程序(組件)通過管道聯結起來,產生總和的效果;還有傳統的編譯器,源代碼經過詞法分析、語法分析、中間代碼生成、目標代碼生成等步驟生成輸出的目標代碼。
優點:
整個系統的功能是多個過濾器作用的總和,這樣可以簡化系統的分析和設計,可以經過需求的分析之後將整個系統作為一個過濾器處理,然後再逐步的細化成為多個相互連接的過濾器。
支持組件的重用,同一個過濾器可以多次出現在系統的不同位置。
易於維護和增強,過濾器可以被替換,可以增加新的過濾器到系統中而不改變原有的過濾器,不改變原來系統的基本功能。
本質上的並發性支持,這種體系結構由於本質上是與各個獨立的過濾器的狀態無關的,與並行的流的通過次序也是無關的,所以並發是一個基本的體系結構自然具有的特性。
缺點:
由於過濾器之間本質上是獨立的,所以設計者必須獨立考慮每一個過濾器的輸入、處理和輸出的過程,對於過濾器邏輯上的共同點和相互關系無法在設計中加以體現。
由於這種體系的批處理特性,所以不適合開發和用戶交互的應用程序。
系統的多個處理流之間的共同特性無法提取、多個過濾器之間的共同特性也無法提取,所以增加了設計的復雜性。
2.面向對象的體系
在這種體系中,數據和數據上的操作被封裝成抽象數據類型或者對象。系統由大量的對象組成,在物理上,對象之間通過函數或者過程調用相互作用;在邏輯上,對象之間通過集成、復合等方式實現設計的復用。
對象D
對象B
對象A
對象E
對象C
對象調用
對象調用
對象調用
類A
類B
類C
類G
對象A
對象E
類F
復合
繼承
物理結構邏輯結構
特點:
面向對象系統分析和設計的資料已經太多,這里就不再詳細說明了。
優點:
由於封裝,實現了靈活性和擴充性,隱藏了實現的細節,提高代碼的質量;
使用繼承和多態、提高了軟體的可重用性。
缺點:
最主要的缺點是,由於對象之間的交互是通過明確的對象函數調用進行的,所以當一個對象需要實現一個特定功能的時候,必須知道哪一個對象提供這種服務,這就降低了系統的靈活性。管道和過濾器模型不需要明確指明數據的來源和去向。
事件驅動的體系
對象E
對象E
對象E
事件分發的匯流排
事件的創建
事件接收者的注冊的創建
對象E
這是面向對象和數據抽象體系的一種變形,系統同樣是由大量的對象組成的,但是對象之間的交互不是通過明確指明對象的函數或者過程調用進行的,相反,系統提供事件的創建和發布的機制,對象產生事件,一個或者多個對象通過向系統注冊關注這個事件並由此觸發出相應的行為或者產生新的事件。
實例:
一個最著名的例子是GUI的模型,滑鼠、鍵盤或者其他輸入設備產生各種事件,窗口、程序或者其他對象有這些事件所觸發,產生新的事件、進行數據處理或者其他操作。
優點:
用於函數和過程的調用調用不需要指明特定的對象,所以系統具有非常好的靈活性和擴展性,新的組件只需要向系統的事件處理部分注冊就可以立刻加入系統中,同樣,老的組件也可以方便的從系統中刪除。對於動態性要求特別高的系統,特別是如果需要在運行時對系統進行擴充,應該採用該結構。
缺點:
由於函數調用是通過事件發送進行的,所以,發出事件的對象不能確認是否有對象處理了這個事件、是否是期望的對象處理了這個事件、是否獲得期望的結果,同樣也無法控制事件發生的次序,系統的邏輯和時序的正確性必須通過復雜的時序邏輯和前後條件的斷言加以保證。
3.分層次的體系
將系統功能和組件分成不同的功能層次,一般而言,只有最上層的組件和功能可以被系統外的使用者訪問,只有相鄰的層次之間才能夠有函數調用。
下面是一個基本的商務處理系統的層次結構:
用戶界面層
事務邏輯層
核心層
實例:
顯然,ISO的OSI(開放系統互連)參考模型是最著名的層次模型的例子,通過將開放系統的功能和組件劃分成7個層次,定義清晰的(很多時候是過於復雜的)層次之間的介面,實現復雜的互操作性。
優點:
系統的開發和設計可以逐步的分層次的進行,從底層的簡單的功能逐步建立高層的復雜和抽象的功能。
靈活性和擴展性,由於相鄰層次之間通過清晰的介面交互,所以特定的層次可以被替換和增強,甚至可以增加新的層次。
缺點:
不是所有的系統都可以分解成為清楚的層次
劃分清晰、邏輯上一致的層次是非常困難的(OSI的失敗和TCP/IP的成功說明了這一點)
嚴格的層次調用結構會降低系統的性能。
4.知識庫體系
使用一個中心數據結構表示系統的當前狀態,一組相互獨立的組件在中心資料庫上進行操作。如果組件負責對中心數據進行選擇、處理,這種體系就是傳統的資料庫模型;如果中心數據結構自主的引發一系列的行為,則這種體系可以看成一個黑板模型。
中心資料庫(知識庫)
客戶組件A
客戶組件B
客戶組件C
實例:
大量的傳統資料庫應用程序實際上就是這一體系的具體實例。在很多研究系統中,使用的基於知識庫的黑板模型,實際上也是這種體系
優點:
以數據為中心的體系結構,可以自然的表示大量的數據和事務處理的邏輯,適合表達以數據為重新的應用程序。
缺點:
只有很少一部分簡單的資料庫存儲應用可以完全採用這種體系結構表示,在大量實際的商業應用中,完成師傅處理和其他邏輯的應用程序必須採用其他的體系結構表達
5.解釋器體系
用戶
如果應用程序的邏輯非常復雜,例如,AutoCAD的各種繪圖指令,而且,用戶可能以非常復雜的方式使用這個系統,一個較好的體系就是提供面向領域的一組指令(語言),系統解釋這種語言,產生相應的行為,用戶使用這種指令(語言)完成復雜的操作。
使用虛擬機語言描述的業務邏輯
虛擬機解釋器
完成實際操作任務的基本指令
實際的問題領域
實例:
大量的開發工具、二次開發工具體現了這一思想:微軟在其產品中大量使用的Visual Basic for Application,以及在AutoDesk產品中大量使用的AutoLisp語言,實際上就是給用戶提供了一種面向領域的語言,然後核心解釋執行這一語言的指令和指令序列。從而擴充產品的功能,方便用戶按照自己的需要定製系統。
優點:
非常好的擴展性,用戶可以實現對軟體系統的二次開發
缺點:
軟體開發復雜,特別是這種指令集的設計非常困難。
是否可以採用一種成熟的語言作為二次開發的基礎(例如,基於Java)
⑦ 編譯器筆記6-詞法分析-有窮自動機
有窮自動機(Finite Automata,FA)由兩位神經物理學MeCuloch和Pitts於1948年首先提出,是對 一類處理系統建立的數學模型。這類系統具有一系列離散的輸入輸出信息和有窮數目的內部狀態(狀態:概括了對過去輸入信息處理的狀況)。
系統只需要根據當前所處的狀態 和 當前面臨的輸入信息就可以決定系統的後繼行為。每當系統處理了當前的輸入後,系統的內部 狀態也將發生改變。
電梯控制裝置
輸入:顧客的乘梯需求(所要到達的層號)
狀態:電梯所處的層數+
電梯控制裝置並不需要記住先前全部的服務要
求,只需要知道電梯當前所處的狀態以及還沒
有滿足的所有服務請求。
輸入帶 (input tape) :用來存放輸入符號串。
讀頭 (head) :從左向右逐個讀取輸入符號,不能修改(只讀)、不能往返移動。
有窮控制器 ( finite control ) :具有有窮個狀態數,根據當前的
狀態和當前輸入符號控制轉入 下一狀態。
確定的FA (Deterministic finite automata, DFA)
非確定的FA (Nondeterministic finite automata, NFA)
M = (S,Σ,δ,s0,F)
例:一個DFA
M = (S,Σ ,δ,s0,F)
M = (S,Σ,δ,s0,F)
例:一個NFA
M = (S,Σ,δ,s0,F)
對任何非確定的有窮自動機N,存在定義同一語言的確定的有窮自動機D。對任何確定的有窮自動機D,存在定義同一語言的非確定的有窮自動機N。
DFA和NFA可以識別相同的語言
M = (S,Σ,δ,s0,F)
從正則表達式到NFA相對直接到DFA比較簡單,再從NFA轉到DFA。
例 r=(a|b)* abb 對應的NFA
與NFA等價的DFA的每個狀態都是NFA狀態的一個子集
move(T,a)獲得的是一個狀態集合U,ε-closure(move(T,a))即為ε-closure(U)對應上表的第二個操作。所以理解上述函數關鍵是理解closure(T),該操作其實就是求得一個狀態集合只通過ε轉換得到的另外一個集合。