1、Java 語(yǔ)言的概述
作為一種面向?qū)ο蟮某绦蛟O(shè)計(jì)語(yǔ)言,Java 與 C++極為 類似,但卻要比 C++簡(jiǎn)單的多。它在集成其他語(yǔ)言的特點(diǎn) 和優(yōu)勢(shì)的同時(shí)又有自己獨(dú)特的優(yōu)勢(shì)。
Java 的主要特點(diǎn)如下:
(1)簡(jiǎn)單性。Java 可以對(duì)內(nèi)存中產(chǎn)生的垃圾進(jìn)行自動(dòng)收集, 大幅度降低了程序的復(fù)雜程度,此外,Java 添加了更為實(shí) 用的功能的,這使得程序開(kāi)發(fā)更加簡(jiǎn)單可靠。
(2)平臺(tái)獨(dú) 立性。Java 語(yǔ)言在程序編程過(guò)程中是先編譯成中間碼,然 后再進(jìn)行裝載與校驗(yàn),最后通過(guò)翻譯出來(lái)的不同的機(jī)器碼 來(lái)執(zhí)行。因此,只要能支持 Java 虛擬機(jī),就可運(yùn)行各種 J ava 程序。這也是 Java 最吸引人、使用方便的原因。
(3) 面向?qū)ο蟮募夹g(shù)。近年來(lái)軟件開(kāi)發(fā)中使用最多的就是面向 對(duì)象的技術(shù)。面向?qū)ο蠹夹g(shù)是指在編程過(guò)程中,以一種更 加直觀的、人們更容易接受的方式來(lái)編程的技術(shù)。而 Java 的動(dòng)態(tài)聯(lián)網(wǎng)編程特性,將面向?qū)ο蟮膬?yōu)勢(shì)發(fā)揮到最大。
2、C 語(yǔ)言的概述
C 語(yǔ)言,作為一種新的程序設(shè)計(jì)語(yǔ)言,它結(jié)合了匯編 語(yǔ)言與高級(jí)語(yǔ)言兩種語(yǔ)言的優(yōu)勢(shì),使得它的應(yīng)用更加簡(jiǎn)單、 普及。如今,C 語(yǔ)言已經(jīng)應(yīng)用于各種類型的微型機(jī)上。在編寫(xiě)程序時(shí),C 語(yǔ)言可以直接進(jìn)行程序的編程。因此,C 語(yǔ)言在應(yīng)用方面十分廣泛,具備很強(qiáng)的數(shù)據(jù)處理能力。C 語(yǔ)言的應(yīng)用已不僅僅是用于軟件開(kāi)發(fā),各類科研都需要用 到 C 語(yǔ)言。
C 語(yǔ)言的優(yōu)點(diǎn):1.是簡(jiǎn)潔緊湊、靈活方便;2.運(yùn)算符 豐富;3.數(shù)據(jù)類型豐富;4.表達(dá)方式靈活多用;5.生成目標(biāo)代碼 質(zhì)量高、程序執(zhí)行效率高;可移植性高。
因?yàn)?C 語(yǔ)言是將 相同數(shù)據(jù)堆放在一塊,這就使得 C 語(yǔ)言的數(shù)據(jù)存在很大的 安全缺陷,一旦出現(xiàn)意外,所有數(shù)據(jù)都將丟失。
此外,C 語(yǔ)言在語(yǔ)法限制以及變量的類型上比較寬松,這樣就會(huì)影 響到程序的安全性。而且 C 語(yǔ)言比其他高級(jí)語(yǔ)言的難度大, 完全掌握是很不易的。
3、c 和 java的 編譯器對(duì)比
Java與C/C++的編譯器對(duì)比實(shí)際上是代表了最經(jīng)典的JIT編譯器與靜態(tài)編譯器的對(duì)比,
(注釋:JIT編譯器,英文寫(xiě)作Just-In-Time Compiler,中文意思是即時(shí)編譯器。JIT編譯器能夠?qū)SIL編譯成為各種不同的機(jī)器代碼,以適應(yīng)對(duì)應(yīng)的系統(tǒng)平臺(tái),最終使得程序在目標(biāo)系統(tǒng)中得到順利地運(yùn)行。 靜態(tài)編譯,就是編譯器在編譯可執(zhí)行文件的時(shí)候,將可執(zhí)行文件 需要調(diào)用的對(duì)應(yīng)動(dòng)態(tài)鏈接庫(kù)(.so或.lib)中的部分提取出來(lái),鏈接到可執(zhí)行文件中去,使可執(zhí)行文件在運(yùn)行的時(shí)候不依賴于動(dòng)態(tài)鏈接庫(kù)。)
也很大程度上決定了Java與C/C++的性能對(duì)比的結(jié)果,
因?yàn)闊o(wú)論是C/C++還是Java代碼,最終編譯之后被機(jī)器執(zhí)行的都是本地機(jī)器碼,哪種語(yǔ)言性能更高,除了它們自身的API庫(kù)實(shí)現(xiàn)得好壞以外,其余的比較就成了一場(chǎng)“拼編譯器”、“拼輸出代碼質(zhì)量”的游戲。
當(dāng)然,這種比較也是剔除了開(kāi)發(fā)效率的片面對(duì)比,語(yǔ)言間孰優(yōu)孰劣,誰(shuí)快誰(shuí)慢的問(wèn)題都是很難有結(jié)果的爭(zhēng)論,下面我們就回到正題,看看這兩種語(yǔ)言的編譯器各有何優(yōu)勢(shì)。
原因如下:
(1)因?yàn)镴IT編譯器運(yùn)行占用的是用戶程序運(yùn)行時(shí)間,具有很大的時(shí)間壓力,它能提供的優(yōu)化手段也嚴(yán)重受制于編譯成本。如果編譯速度不能達(dá)到要求,那用戶將在啟動(dòng)程序或程序的某部分察覺(jué)到重大延遲,這點(diǎn)使得JIT編譯器不敢隨便引入大規(guī)模的優(yōu)化技術(shù),而編譯的時(shí)間成本在靜態(tài)優(yōu)化編譯器中并不是主要的關(guān)注點(diǎn)。
(2),Java語(yǔ)言是動(dòng)態(tài)的類型安全語(yǔ)言,這意味著需要由虛擬機(jī)來(lái)確保程序不會(huì)違反語(yǔ)言語(yǔ)義或訪問(wèn)非結(jié)構(gòu)化內(nèi)存。在實(shí)現(xiàn)層面上看,這就意味著虛擬機(jī)必須頻繁進(jìn)行動(dòng)態(tài)檢查,如對(duì)象實(shí)例訪問(wèn)時(shí)檢查空指針、數(shù)組元素訪問(wèn)時(shí)檢查上下界范圍、類型轉(zhuǎn)換時(shí)檢查繼承關(guān)系等等。對(duì)于這類程序代碼沒(méi)有明確寫(xiě)出的檢查行為,盡管編譯器會(huì)努力進(jìn)行優(yōu)化,但是總體上仍然要消耗著不少的運(yùn)行時(shí)間。
?。?)Java語(yǔ)言中雖然沒(méi)有virutal關(guān)鍵字,但是使用虛方法的頻率卻遠(yuǎn)遠(yuǎn)大于C/C++語(yǔ)言,這意味著運(yùn)行時(shí)對(duì)方法接收者進(jìn)行多態(tài)選擇的頻率要遠(yuǎn)遠(yuǎn)大于C/C++語(yǔ)言,也意味著JIT編譯器在進(jìn)行一些優(yōu)化,如方法內(nèi)聯(lián)時(shí)難度要遠(yuǎn)大于C/C++的靜態(tài)優(yōu)化編譯器。
?。?)Java語(yǔ)言是可以動(dòng)態(tài)擴(kuò)展的語(yǔ)言,運(yùn)行時(shí)加載新的類可能改變程序類型繼承關(guān)系,這使得很多全局的優(yōu)化都難以進(jìn)行,因?yàn)榫幾g器無(wú)法看見(jiàn)程序的全貌,許多全局優(yōu)化措施都只能以激進(jìn)優(yōu)化的方式來(lái)完成,編譯器不得不時(shí)刻注意并隨著類型變化而在運(yùn)行是撤消或重新進(jìn)行一些優(yōu)化。
?。?)Java語(yǔ)言中的對(duì)象內(nèi)存分配都是堆上進(jìn)行,只有方法中的局部變量才在棧上分配。而C/C++的對(duì)象則有多種內(nèi)存分配方式,既可能在堆上分配,也可能在棧上分配,如果可以把線程私有的對(duì)象在棧上分配,將可以減輕內(nèi)存回收的壓力,也不需要考慮內(nèi)存屏障方面的問(wèn)題。另外,C/C++中主要由用戶程序代碼來(lái)回收分配的內(nèi)存,這就不存在無(wú)用對(duì)象篩選的過(guò)程,因此效率上(僅指運(yùn)行效率,排除了開(kāi)發(fā)效率)也垃圾收集機(jī)制要高。
(6)因?yàn)镃是編譯型的,直接將源碼編譯成機(jī)器代碼;而JAVA是解釋型,源碼被編譯成二進(jìn)制偽代碼,由JAVA虛擬機(jī)解釋執(zhí)行。但是,由于C是編譯型的,它的可移植性差;而JAVA是解釋執(zhí)行,因此具有很好的移植性,可跨平臺(tái)運(yùn)行。
同時(shí):編一個(gè)普通的本地應(yīng)用程序,一般c 要快于java, 編web應(yīng)用,由于c實(shí)現(xiàn)的cgi程序基本是進(jìn)程型,而java application server 的管理servlet采用線程方式,所以,在訪問(wèn)量大的情況下,java有優(yōu)勢(shì)。
?。╢inally)Java語(yǔ)言相對(duì)C/C++的劣勢(shì)上面說(shuō)了一大堆,倒不是說(shuō)Java就真的不如C/C++了,相信大家也注意到了,Java語(yǔ)言的這些性能上的劣勢(shì)都是為了換取開(kāi)發(fā)效率上的優(yōu)勢(shì)而付出的代價(jià),動(dòng)態(tài)安全、動(dòng)態(tài)擴(kuò)展、垃圾回收這些“拖后腿”特性都為Java語(yǔ)言的開(kāi)發(fā)效率作出了很大貢獻(xiàn)。何況,也不見(jiàn)得就沒(méi)有Java的JIT編譯器能做,而C/C++的靜態(tài)優(yōu)化編譯器不能做的優(yōu)化:由于C/C++編譯器的靜態(tài)性,以運(yùn)行期性能監(jiān)控為基礎(chǔ)的優(yōu)化措施它都無(wú)法進(jìn)行,如調(diào)用頻率預(yù)測(cè)(Call Frequency Prediction)、分支頻率預(yù)測(cè)(Branch Frequency Prediction)、裁剪未被選擇的分支(Untaken Branch Pruning)等,這些都會(huì)形成一些Java語(yǔ)言獨(dú)有的性能優(yōu)勢(shì)
4、Java程序比C/C++程序慢的影響因素
1)解釋性語(yǔ)言固有開(kāi)銷:java程序在運(yùn)行時(shí)類加載器從類路經(jīng)中加載相關(guān)的類,然后java虛擬機(jī)讀取該類文件的字節(jié),執(zhí)行相應(yīng)操作.而C 編譯的時(shí)候?qū)⒊绦蚓幾g成本地機(jī)器碼.一般來(lái)說(shuō)java程序執(zhí)行速度要比C 慢10-30倍.即使采用just-in-time compiling (讀取類文件字節(jié)后,編譯成本地機(jī)器碼)技術(shù),速度也要比C 慢好多.
2)字節(jié)碼加載執(zhí)行開(kāi)銷:java程序要從網(wǎng)絡(luò)上加載類字節(jié),然后執(zhí)行,這也是導(dǎo)致java運(yùn)行速度慢的原因.
3)運(yùn)行時(shí)溢出檢測(cè)開(kāi)銷:在程序運(yùn)行過(guò)程中,java虛擬機(jī)要檢測(cè)數(shù)組是否越界,在C 中則不檢測(cè).
4)堆與棧的區(qū)別:java中所有的對(duì)象都創(chuàng)建在堆中,沒(méi)有對(duì)象被創(chuàng)建在stack中,而C 有的對(duì)象和變量是創(chuàng)建在stack中的
5)運(yùn)行時(shí)引用檢測(cè)開(kāi)銷:java在運(yùn)行過(guò)程中檢測(cè)對(duì)象的引用是否為空,如果引用指向都空指針,且執(zhí)行某個(gè)方法時(shí)會(huì)拋出空指針異常
6)運(yùn)行時(shí)類型檢測(cè)開(kāi)銷:java運(yùn)行時(shí)對(duì)類型檢測(cè),如果類型不正確會(huì)拋出ClassCastException異常.
7)GC巨大開(kāi)銷:java的垃圾回收機(jī)制較C 由程序員管理內(nèi)存效率更低.
8)類型轉(zhuǎn)換開(kāi)銷:java中的原始數(shù)據(jù)類型在每個(gè)操作系統(tǒng)平臺(tái)長(zhǎng)度都是相同,而C 這些數(shù)據(jù)類型長(zhǎng)度是隨操作系統(tǒng)的不同而不同,所以java在不同操作系統(tǒng)上執(zhí)行時(shí)有個(gè)轉(zhuǎn)化過(guò)程.
9)String類型開(kāi)銷:在java中String 是UNICODE.當(dāng)java要操作一個(gè) ASCII string 時(shí),比C 效率上相對(duì)要低一些.
10)動(dòng)態(tài)鏈接開(kāi)銷:java中采用的是動(dòng)態(tài)鏈接
5、結(jié)論
綜上所述,C 語(yǔ)言的運(yùn)行效率 要比 Java 的高很多(有人說(shuō)是高10-30倍)。因?yàn)?C 語(yǔ)言是屬于編譯型的,而 Java 語(yǔ)言則是解釋型的。Java 語(yǔ)言運(yùn)行時(shí)要先被翻譯成計(jì)算機(jī)能 辨識(shí)的二進(jìn)制代碼,然后才能執(zhí)行。雖然在一些的程序測(cè)試 中 C 語(yǔ)言要快于 Java 語(yǔ)言,但這并不是絕對(duì)的。在實(shí)際中, 要根據(jù)不同語(yǔ)言應(yīng)用范圍,才能選擇某一語(yǔ)言程序。
以上就是關(guān)于 Java 語(yǔ)言和 C 語(yǔ)言之間的運(yùn)行效率對(duì)比的全部?jī)?nèi)容,想要了解更多相關(guān) java 和 C 語(yǔ)言的其他內(nèi)容請(qǐng)搜索W3Cschool以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,也希望大家以后多多支持我們!