java忽略依賴編譯類
程序開始處所出現的import語句是導入JAVA程序源代碼編輯時所需要的類庫,如果你所配置的JDK中不包含這些類庫,並且沒有將所使用的類庫導入到ECLIPSE對應的工程中,程序將報錯到import語句處。當程序中有任何語法錯誤時,JAVA虛擬機(JVM)將不能順利編譯程序,自然你的代碼就無法編譯通過。Eclipse編輯器中的紅色標記也不是完全沒有才可以通過編譯,在識別頁面文件(JSP、HTML、XML) 的時候,ECLIPSE會出現一些莫名其妙的報紅,此時可先忽略,待編譯後仍然不能通過再進行修改,頁面或者XML文件等文件往往會出現此類現象。
❷ java有依賴的jar 怎麼編譯
手動導入相應的jar包,找到需要的類(如果用IDE工具的話,自動import)然後import進去,就可以正常編譯和實現對應的功能。
❸ java怎麼根據word邐募蓋ord文件,解決了立馬給分
Java是一種廣泛使用的計算機編程語言,擁有跨平台、面向對象、泛型編程的特性,廣泛應用於企業級Web應用開發和移動應用開發。
任職於太陽微系統的詹姆斯·高斯林等人於1990年代初開發Java語言的雛形,最初被命名為Oak,目標設置在家用電器等小型系統的程序語言,應用在電視機、電話、鬧鍾、烤麵包機等家用電器的控制和通信。由於這些智能化家電的市場需求沒有預期的高,Sun公司放棄了該項計劃。隨著1990年代互聯網的發展,Sun公司看見Oak在互聯網上應用的前景,於是改造了Oak,於1995年5月以Java的名稱正式發布。Java伴隨著互聯網的迅猛發展而發展,逐漸成為重要的網路編程語言。
Java編程語言的風格十分接近C++語言。繼承了C++語言面向對象技術的核心,Java舍棄了C++語言中容易引起錯誤的指針,改以引用取代,同時移除原C++與原來運算符重載,也移除多重繼承特性,改用介面取代,增加垃圾回收器功能。在Java SE 1.5版本中引入了泛型編程、類型安全的枚舉、不定長參數和自動裝/拆箱特性。太陽微系統對Java語言的解釋是:「Java編程語言是個簡單、面向對象、分布式、解釋性、健壯、安全與系統無關、可移植、高性能、多線程和動態的語言」
Java不同於一般的編譯語言或直譯語言。它首先將源代碼編譯成位元組碼,然後依賴各種不同平台上的虛擬機來解釋執行位元組碼,從而實現了「一次編寫,到處運行」的跨平台特性。在早期JVM中,這在一定程度上降低了Java程序的運行效率。但在J2SE1.4.2發布後,Java的運行速度有了大幅提升。
與傳統類型不同,Sun公司在推出Java時就將其作為開放的技術。全球數以萬計的Java開發公司被要求所設計的Java軟體必須相互兼容。「Java語言靠群體的力量而非公司的力量」是 Sun公司的口號之一,並獲得了廣大軟體開發商的認同。這與微軟公司所倡導的注重精英和封閉式的模式完全不同,此外,微軟公司後來推出了與之競爭的.NET平台以及模仿Java的C#語言。後來Sun公司被甲骨文公司並購,Java也隨之成為甲骨文公司的產品。
現時,移動操作系統Android大部分的代碼採用Java 編程語言編程。
早期的Java
Java的發明人詹姆斯·高斯林
Duke,Java語言的吉祥物
語言最開始只是Sun計算機(Sun MicroSystems)公司在1990年12月開始研究的一個內部項目。Sun計算機公司的一個叫做帕特里克·諾頓的工程師被公司自己開發的C++和C語言編譯器搞得焦頭爛額,因為其中的API極其難用。帕特里克決定改用NeXT,同時他也獲得了研究公司的一個叫做「Stealth計劃」的項目的機會。
「Stealth計劃」後來改名為「Green計劃」,詹姆斯·高斯林和麥克·舍林丹也加入了帕特里克的工作小組。他們和其他幾個工程師一起在加利福尼亞州門羅帕克市沙丘路的一個小工作室裡面研究開發新技術,瞄準下一代智能家電(如微波爐)的程序設計,Sun公司預料未來科技將在家用電器領域大顯身手。團隊最初考慮使用C++語言,但是很多成員包括Sun的首席科學家比爾·喬伊,發現C++和可用的API在某些方面存在很大問題。
工作小組使用的是嵌入式系統,可以用的資源極其有限。很多成員發現C++太復雜以至很多開發者經常錯誤使用。他們發現C++缺少垃圾回收系統,還有可移植的安全性、分布程序設計、和多線程功能。最後,他們想要一種易於移植到各種設備上的平台。
根據可用的資金,喬伊決定開發一種集C語言和Mesa語言大成的新語言,在一份報告上,喬伊把它叫做「未來」,他提議Sun公司的工程師應該在C++的基礎上,開發一種面向對象的環境。最初,高斯林試圖修改和擴展C++的功能,他自己稱這種新語言為C++ ++ --,但是後來他放棄了。他將要創造出一種全新的語言,被他命名為「Oak」(橡樹),以他的辦公室外的橡樹命名。
就像很多開發新技術的秘密工程一樣,工作小組沒日沒夜地工作到了1993年的夏天,他們能夠演示新平台的一部分了,包括Green操作系統,Oak的程序設計語言,類庫及其硬體。最初的嘗試是面向一種類PDA設備,被命名為Star7,這種設備有鮮艷的圖形界面和被稱為「Duke」的智能代理來幫助用戶。1992年12月3日,這台設備進行了展示。
同年11月,Green計劃被轉化成了「FirstPerson有限公司」,一個Sun公司的全資子公司,團隊也被重新安排到了帕洛阿爾托。FirstPerson團隊對建造一種高度交互的設備感興趣,當時代華納發布了一個關於電視機頂盒的徵求提議書時(Request for proposal),FirstPerson改變了他們的目標,作為對徵求意見書的響應,提出了一個機頂盒平台的提議。但是有線電視業界覺得FirstPerson的平台給予用戶過多的控制權,因此FirstPerson的投標敗給了SGI。與3DO公司的另外一筆關於機頂盒的交易也沒有成功,由於他們的平台不能在電視工業產生任何效益,公司被並回Sun公司。
Java和互聯網
1994年6月,在經歷了一場歷時三天的腦力激盪的討論後,約翰·蓋吉、詹姆斯·高斯林、比爾·喬伊、帕特里克·諾頓、韋恩·羅斯因和埃里克·斯庫米,團隊決定再一次改變了努力的目標,這次他們決定將該技術應用於萬維網。他們認為隨著Mosaic瀏覽器的到來,網際網路正在向同樣的高度互動的遠景演變,而這一遠景正是他們在有線電視網中看到的。作為原型,帕特里克·諾頓寫了一個小型萬維網瀏覽器,WebRunner,後來改名為HotJava[12]。
1994年10月,HotJava和Java平台為公司高層進行演示。1994年,Java
1.0a版本已經可以提供下載,但是Java和HotJava瀏覽器的第一次公開發布卻是在1995年3月23日SunWorld大會上進行的。升陽公司的科學指導約翰·蓋吉宣告Java技術。這個發布是與網景公司的執行副總裁馬克·安德森的驚人發布一起進行的,宣布網景將在其瀏覽器中包含對Java的支持。1996年1月,升陽公司成立了Java業務集團,專門開發Java技術。
Java和「Java」
由於商標搜索顯示,Oak已被一家顯示卡製造商注冊。於是同年,Oak被改名為Java。當使用十六進制編輯器打開由Java源代碼編譯出的二進制文件(.class文件)的話,最前面的32位將顯示為CA FE BA BE,即片語「CAFE BABE」(咖啡屋寶貝)。
Java近況
一套Java編輯器軟體
J2SE環境與CDC的關連
JVM的所在角色
JSPX網頁的概念
在流行幾年之後,Java在瀏覽器中的地位被逐步侵蝕。它在簡單交互性動畫方面的用途已經完全被Adobe公司的Flash排擠,2005年Java傾向只被用於雅虎游戲那樣的更為復雜的應用程序。Java同時遭受到來自微軟的反對,他們決定在新版本的Internet Explorer和Windows中不再附帶Java平台。
與此相反。在萬維網的伺服器端和手持設備上,Java變得更加流行。很多網站在後端使用JSP和其他的Java技術。
在桌面系統上,獨立的Java程序還是相對少見,這是因為Java平台的運行開銷較大,而許多人的電腦上沒有安裝Java,由於網路帶寬在以前較小,下載Java曾經是個耗時的事情。但是隨著計算機計算能力、網路帶寬在10年中獲取了很大的進步,同時虛擬機和編譯器的質量得到了提高,許多應用程序得到了廣泛的使用,包括:
開源軟體:
NetBeans和Eclipse等軟體開發工具
Android操作系統
JEdit
Azureus BitTorrent客戶端。
JNode操作系統
Apache軟體基金會的Ant、Derby、Hadoop、Jakarta、POI和Tomcat
JBoss和GlassFish應用伺服器
商業軟體:
EIOffice(永中Office)
Minecraft
純Java 3D游戲合金戰士Chrome
IBM Websphere、ColdFusion和WebLogic
IntelliJ IDEA
還有許多用Java寫的軟體,可以在http://www.java.com 找到。在以下網頁可以看到非常多用Java寫的程序:http://java.sun.com/procts/ 下面有大量用Java Swing開發的桌面Java程序 http://java.sun.com/procts/jfc/tsc/sightings/ 目前Java提供以下三個版本:
Java Platform, Enterprise Edition(Java EE:Java平台企業版)
Java Platform, Standard Edition(Java SE:Java平台標准版)
Java Platform, Micro Edition(Java ME:Java平台微型版)
Java Platform, Card Edition
Java開放源代碼項目
2006年SUN在JavaOne公布Java 開放源代碼項目,並推出OpenJDK項目。[13]Java虛擬機、Java編譯器和Java類庫以GNU通用公共許可證公開。
版本歷史
主條目:Java版本歷史
1995年5月23日,Java語言誕生
1996年1月,第一個JDK-JDK1.0誕生
1996年4月,10個最主要的操作系統供應商申明將在其產品中嵌入JAVA技術
1996年9月,約8.3萬個網頁應用了JAVA技術來製作
1997年2月18日,JDK1.1發布
1997年4月2日,JavaOne會議召開,參與者逾一萬人,創當時全球同類會議規模之紀錄
1997年9月,JavaDeveloperConnection社區成員超過十萬
1998年2月,JDK1.1被下載超過2,000,000次
1998年12月8日,JAVA2企業平台J2EE發布
1999年6月,SUN公司發布Java的三個版本:標准版(J2SE)、企業版(J2EE)和微型版(J2ME)
2000年5月8日,JDK1.3發布
2000年5月29日,JDK1.4發布
2001年6月5日,NOKIA宣布,到2003年將出售1億部支持Java的手機
2001年9月24日,J2EE1.3發布
2002年2月26日,J2SE1.4發布,自此Java的計算能力有了大幅提升
2004年9月30日18:00PM,J2SE1.5發布,成為Java語言發展史上的又一里程碑。為了表示該版本的重要性,J2SE1.5更名為Java SE 5.0
2005年6月,JavaOne大會召開,SUN公司公開Java SE 6。此時,Java的各種版本已經更名,以取消其中的數字「2」:J2EE更名為Java EE,J2SE更名為Java SE,J2ME更名為Java ME
2006年12月,SUN公司發布JRE6.0
2009年12月,SUN公司發布Java EE 6
2010年11月,由於Oracle公司對於Java社區的不友善,因此Apache揚言將退出JCP[14]
2011年7月28日,Oracle公司發布Java SE 7
2014年3月18日,Oracle公司發表Java SE 8
語言特性
Java之所以被開發,是要達到以下五個目的:
應當使用面向對象程序設計方法學
應當允許同一程序在不同的計算機平台執行
應當包括內建的對計算機網路的支持
應當被設計成安全地執行遠端代碼
應當易於使用,並借鑒以前那些面向對象語言(如C++)的長處。
Java技術主要分成幾個部分:Java語言、Java運行環境、類庫。一般情況下說Java時並不區分指的是哪個部分。
Java在1.5版本時,做了重大改變,Sun公司並1.5版本重命名為Java 5.0。
面向對象
Java的特點之一就是面向對象,是程序設計方法的一種。「面向對象程序設計語言」的核心之一就是開發者在設計軟體的時候可以使用自定義的類型和關聯操作。代碼和數據的實際集合體叫做「對象」。一個對象可以想像成綁定了很多「行為(代碼)」和「狀態(數據)」的物體。對於數據結構的改變需要和代碼進行通信然後操作,反之亦然。面向對象設計讓大型軟體工程的計劃和設計變得更容易管理,能增強工程的健康度,減少失敗工程的數量。
跨平台性
Java語言的第二個特性就是跨平台性,也就是說使用Java語言編寫的程序可以在編譯後不用經過任何更改,就能在任何硬體設備條件下運行。這個特性經常被稱為「一次編譯,到處運行」。
執行Java應用程序必須安裝爪哇運行環境(Java Runtime Environment,JRE),JRE內部有一個Java虛擬機(Java Virtual Machine,JVM)以及一些標準的類庫(Class Library)。通過JVM才能在電腦系統執行Java應用程序(Java Application),這與.Net Framework的情況一樣,所以電腦上沒有安裝JVM,那麼這些程序將不能夠執行。
實現跨平台性的方法是大多數編譯器在進行Java語言程序的編碼時候會生成一個用位元組碼寫成的「半成品」,這個「半成品」會在Java虛擬機(解釋層)的幫助下運行,虛擬機會把它轉換成當前所處硬體平台的原始代碼。之後,Java虛擬機會打開標准庫,進行數據(圖片、線程和網路)的訪問工作。主要注意的是,盡管已經存在一個進行代碼翻譯的解釋層,有些時候Java的位元組碼代碼還是會被JIT編譯器進行二次編譯。
有些編譯器,比如GCJ,可以自動生成原始代碼而不需要解釋層。但是這些編譯器所生成的代碼只能應用於特定平台。並且GCJ目前只支持部分的Java API。
甲骨文公司對於Java的許可是「全兼容的」,這也導致了微軟和升陽關於微軟的程序不支持RMI和JNI介面、並且增加特性為己所用的法律爭端。升陽最終贏得了官司,獲得了大約兩千萬美元的賠償,法院強制要求微軟執行升陽公司關於Java的許可要求。作為回應,微軟不再在Windows系統中捆綁Java,最新的Windows版本,Windows Vista和Internet Explorer 7.0版本也不再提供對於Java應用程序和控制項的支持。但是升陽公司和其他使用Java運行時系統的公司在Windows操作系統下對用戶提供無償的第三方插件和程序支持。
Java語言使用解釋層最初是為了輕巧性。所以這些程序的運行效率比C語言和C++要低很多,用戶也對此頗有微詞。很多最近的調查顯示Java的程序運行速度比幾年前要高出許多,有些同樣功能的程序的效率甚至超過了C++和C語言編寫的程序[來源請求]。
Java語言在最開始應用的時候是沒有解釋層的,所有需要編譯的代碼都直接轉換成機器的原始代碼。這樣做的後果就是獲得了最佳的性能,但是程序臃腫異常。從JIT技術開始,Java的程序都經過一次轉換之後才變成機器碼。很多老牌的第三方虛擬機都使用一種叫做「動態編譯」的技術,也就是說虛擬機實時監測和分析程序的運行行為,同時選擇性地對程序所需要的部分進行編譯和優化。所有這些技術都改善了代碼的運行速度,但是又不會讓程序的體積變得失常。
程序的輕便性事實上是軟體編寫很難達到的一個目標,Java雖然成功地實現了「一次編譯,到處運行」,但是由於平台和平台之間的差異,所編寫的程序在轉換代碼的時候難免會出現微小的、不可察覺的錯誤和意外。有些程序員對此非常頭疼,他們嘲笑Java的程序不是「一次編譯,到處運行」,而是「一次編譯,到處調試」。以Java
AWT為例,早期Java
AWT內提供的按鈕、文字區等均是以計算機系統所默認的樣式而顯示。這令Java程序在有些沒有提供圖案的計算機系統產生錯誤(在Microsoft
Windows設有窗口管理器,在一些Linux distribution則沒有)。後來SUN公司針對Java AWT一些問題而推出Java
Swing。
平台無關性讓Java在伺服器端軟體領域非常成功。很多伺服器端軟體都使用Java或相關技術建立。
自動垃圾回收(Garbage Collection)
C++語言被用戶詬病的原因之一是大多數C++編譯器不支持垃圾收集機制。通常使用C++編程的時候,程序員於程序中初始化對象時,會在主機內存堆棧上分配一塊內存與地址,當不需要此對象時,進行析構或者刪除的時候再釋放分配的內存地址。如果對象是在堆棧上分配的,而程序員又忘記進行刪除,那麼就會造成內存泄漏(Memory
Leak)。長此以往,程序運行的時候可能會生成很多不清除的垃圾,浪費了不必要的內存空間。而且如果同一內存地址被刪除兩次的話,程序會變得不穩定,甚至崩潰。因此有經驗的C++程序員都會在刪除之後將指針重置為NULL,然後在刪除之前先判斷指針是否為NULL。
C++中也可以使用「智能指針」(Smart Pointer)或者使用C++託管擴展編譯器的方法來實現自動化內存釋放,智能指針可以在標准類庫中找到,而C++
(題主你怎麼可以問這么沙比的問題!)
託管擴展被微軟的Visual
C++
7.0及以上版本所支持。智能指針的優點是不需引入緩慢的垃圾收集機制,而且可以不考慮線程安全的問題,但是缺點是如果不善使用智能指針的話,性能有可能不如垃圾收集機制,而且不斷地分配和釋放內存可能造成內存碎片,需要手動對堆進行壓縮。除此之外,由於智能指針是一個基於模板的功能,所以沒有經驗的程序員在需要使用多態特性進行自動清理時也可能束手無策。
Java語言則不同,上述的情況被自動垃圾收集功能自動處理。對象的創建和放置都是在內存堆棧上面進行的。當一個對象沒有任何引用的時候,Java的自動垃圾收集機制就發揮作用,自動刪除這個對象所佔用的空間,釋放內存以避免內存泄漏。
注意程序員不需要修改finalize方法,自動垃圾收集也會發生作用。但是內存泄漏並不是就此避免了,當程序員疏忽大意地忘記解除一個對象不應該有的引用時,內存泄漏仍然不可避免。
不同廠商、不同版本的JVM中的內存垃圾回收機制並不完全一樣,通常越新版本的內存回收機制越快,IBM、BEA、SUN等等開發JVM的公司都曾宣稱過自己製造出了世界上最快的JVM[來源請求],JVM性能的世界紀錄也在不斷的被打破並提高。
IBM有一篇有關Java內存回收機制比不激活垃圾收集機制的C++內存處理快數倍的技術文章[15],而著名的Java技術書籍《Java編程思想》(Thinking in Java)也有一段論述Java內存及性能達到甚至超過C++的章節[16]。
基本語法
編寫Java程序前應注意以下幾點:
大小寫敏感:Java是大小寫敏感的,這就意味著標識符Hello與hello是不同的。
類名:對於所有的類來說,類名的首字母應該大寫。如果類名由若干單片語成,那麼每個單詞的首字母應該大寫,例如MyFirstJavaClass。
方法名:所有的方法名都應該以小寫字母開頭。如果方法名含有若干單詞,則後面的每個單詞首字母大寫,例如myFirstJavaMethod。
源文件名:源文件名必須和類名相同。當保存文件的時候,你應該使用類名作為文件名保存(切記Java是大小寫敏感的),文件名的後綴為.java。(如果文件名和類名不相同則會導致編譯錯誤)。
主方法入口:所有的Java程序由public static void main(String[] args)方法開始執行。
Java關鍵字
關鍵字 下面列出了Java關鍵字。這些關鍵字不能用於常量、變數、和任何標識符的名稱。
關鍵字
描述
abstract
抽象方法,抽象類的修飾符
assert
斷言條件是否滿足
continue
不執行循環體剩餘部分
default
switch語句中的默認分支
do-while
循環語句,循環體至少會執行一次
double
64-bit雙精度浮點數
else
if條件不成立時執行的分支
enum
枚舉類型
extends
表示一個類是另一個類的子類
final
表示定義常量
finally
無論有沒有異常發生都執行代碼
float
32-bit單精度浮點數
for
for循環語句
goto
用於流程跳轉(不可用,意即不可隨意跳轉)
if
條件語句
implements
表示一個類實現了介面
import
導入類
instanceof
測試一個對象是否是某個類的實例
int
32位整型數
interface
介面,一種抽象的類型,僅有方法和常量的定義
long
64位整型數
native
表示方法用非java代碼實現
new
分配新的類實例
package
一系列相關類組成一個包
private
表示私有欄位,或者方法等,只能從類內部訪問
protected
表示保護類型欄位
public
表示共有屬性或者方法
return
方法返回值
short
16位數字
static
表示在類級別定義,所有實例共享的
strictfp
浮點數比較使用嚴格的規則
super
表示基類
switch
選擇語句
synchronized
表示同一時間只能由一個線程訪問的代碼塊
this
調用當前實例或者調用另一個構造函數
throw
拋出異常
throws
定義方法可能拋出的異常
transient
修飾不要序列化的欄位
try
表示代碼塊要做異常處理
void
標記方法不返回任何值
volatile
標記欄位可能會被多個線程同時訪問,而不做同步
while
while循環
注釋
注釋作用:標識程序是干什麼的,以及它是如何構建的。注釋幫助程序員進行相互溝通以及理解程序。注釋不是程序設計語言,所以編譯器編譯程序時忽略它們。
介面和類別
Java自帶了創建介面的類別,可以這樣使用:
public interface Deleteable {
void delete();
}
這段代碼的意思是任何實現(implement)Deleteable介面的類別都必須實現delete()方法。每個類別對這個方法的實現可以自行定製。由此概念可以引出很多種使用方法,下面是一個類別的例子:
❹ java 缺少引用類能正確編譯嗎
不可以
比如
publicclassGotDeps{
publicstaticvoidmain(String[]args){
inti=1;
Dep.foo(i);
}
}
Dep的foo方法簽名是
publicstaticvoidfoo(intn)
編譯之後會產生如下命令:
publicstaticvoidmain(java.lang.String[]);
Code:
0:iconst_1
1:istore_1
2:iload_1
3:invokestatic#16;//MethodDep.foo:(I)V
6:return
如果簽名是
publicstaticvoidfoo(longn)
編譯之後的命令:
publicstaticvoidmain(java.lang.String[]);
Code:
0:iconst_1
1:istore_1
2:iload_1
3:i2l
4:invokestatic#16;//MethodDep.foo:(J)V
7:return
所以java編譯器並不知道這些信息,你讓它怎麼編譯?因此是不可以的
❺ ant 編譯忽略某個java類
以前了解過一點
<!--fileset可以設定一組文件集來進行操作,dir指明文件集要進行選擇的路徑,
通過id可以指定這個文件的名稱,在使用的時候進行直接的引入
include和exclude可以設定包含返回和排除范圍**/*.*所有目錄中的所有文件
-->
<fileset id="src.path" dir="src">
<include name="**/*.*"/>
<!--<exclude name="**/*.java"/>-->
</fileset>
❻ 有哪些防止反編譯 Java 類庫 jar 文件的辦法
java本就是開源的,你加密感覺怪怪的。
想防止反編譯,最簡單的方法就是你可以向Jar注入無效代碼。比如建一個類,建一個沒有意義的方法private class Invalid{ },然後輸出為jar。用解壓縮軟體打開這個jar,以文本方式找到那個類的class,然後將那個方法名的一個字母刪掉,然後更新入壓縮文件中。用jd-gui反編譯提示錯誤。這種方式不能用於android中。
還有種方法就是混淆代碼,加密class和高級加密class,方式比較復雜,可以自行網路。
❼ 是否能把JAVA轉化成一個不依賴環境的EXE文件
這個應該可以,不過很復雜:
1 Java應用程序必須在有Jar(java運行環境)的機器上才能運行。否則間不能運行。
2 有專門的java打包軟體,比如:InstallAnyWhere,它可以將Java源程序,包括資料庫,Jar等捆綁在一起,生成一個安裝包,拿到別的機器上安裝就可以使用了。但InstallAnyWhere是英文版的,操作起來不太容易,那個細節配置錯了,打包就不會成功。你還是可以試試!
3 很少用Java做exe的文件,一般都用VC++,.NET,Delphi等開發桌面應用程序。既然學Java,就應該朝著重點方向去學(Java Web方面)。
❽ java程序運行的五個步驟
1、Java程序從源文件創建到程序運行要經過兩大步驟:1、源文件由編譯器編譯成位元組碼(ByteCode) 2、位元組碼由java虛擬機解釋運行。因為java程序既要編譯同時也要經過JVM的解釋運行,所以說Java被稱為半解釋語言("semi-interpreted" language)。
第一步(編譯): 創建完源文件之後,程序會先被編譯為.class文件。Java編譯一個類時,如果這個類所依賴的類還沒有被編譯,編譯器就會先編譯這個被依賴的類,然後引用,否則直接引用,這個有點像make。如果java編譯器在指定目錄下找不到該類所其依賴的類的.class文件或者.java源文件的話,編譯器話報「cant find symbol」的錯誤。
編譯後的位元組碼文件格式主要分為兩部分:常量池和方法位元組碼。常量池記錄的是代碼出現過的所有token(類名,成員變數名等等)以及符號引用(方法引用,成員變數引用等等);方法位元組碼放的是類中各個方法的位元組碼。
第二步(運行):java類運行的過程大概可分為兩個過程:1、類的載入 2、類的執行。需要說明的是:JVM主要在程序第一次主動使用類的時候,才會去載入該類。也就是說,JVM並不是在一開始就把一個程序就所有的類都載入到內存中,而是到不得不用的時候才把它載入進來,而且只載入一次。
2、下面是程序運行的詳細步驟:
在編譯好java程序得到Main.class文件後,在命令行上敲java Main。系統就會啟動一個jvm進程,jvm進程從classpath路徑中找到一個名為Main.class的二進制文件,將Main的類信息載入到運行時數據區的方法區內,這個過程叫做Main類的載入。
然後JVM找到Main的主函數入口,開始執行main函數。
main函數的第一條命令是Animal animal = new Animal("Puppy");就是讓JVM創建一個Animal對象,但是這時候方法區中沒有Animal類的信息,所以JVM馬上載入Animal類,把Animal類的類型信息放到方法區中。
載入完Animal類之後,Java虛擬機做的第一件事情就是在堆區中為一個新的Animal實例分配內存, 然後調用構造函數初始化Animal實例,這個Animal實例持有著指向方法區的Animal類的類型信息(其中包含有方法表,java動態綁定的底層實現)的引用。
當使用animal.printName()的時候,JVM根據animal引用找到Animal對象,然後根據Animal對象持有的引用定位到方法區中Animal類的類型信息的方法表,獲得printName()函數的位元組碼的地址。
開始運行printName()函數。
❾ java文件不用javac編譯(專家級別問題)
javac只是一個java編譯器的命令行界面(shell)。java開源以後,編譯器也可以被編程操作
//獲得編譯器對象
JavaCompiler c=ToolProvider.getSystemJavaCompiler();
CompilationTask t=c.getTask(.... );//獲得編譯任務,參數可以是文件或源碼字元串的流
t.call();//開始編譯
❿ 關於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解釋器程序的平台下運行。