漫話:如何給女友解釋什麼是編譯與反編譯

某天下班後,我在家裏進行電話面試,問到面試者這樣一個問題:"你知道使用哪些辦法能夠反編譯Java代碼嗎?"。可是面試者回答的並很差,因此我在面試評價中寫到:"對編譯原理相關知識理解的不透徹"。這時,女友看到這句話。html

計算機語言前端

計算機語言(Computer Language)指用於人與計算機之間通信的語言。計算機語言是人與計算機之間傳遞信息的媒介。java

計算機系統最大特徵是指令經過一種語言傳達給機器。爲了使電子計算機進行各類工做,就須要有一套用以編寫計算機程序的數字、字符和語法規劃,由這些字符和語法規則組成計算機各類指令(或各類語句)。這些就是計算機能接受的語言。python

計算機語言包括機器語言、彙編語言和高級語言三種。c++

機器語言程序員

機器語言是用二進制代碼表示的計算機能直接識別和執行的一種機器指令的集合。機器語言具備靈活、直接執行和速度快等特色。可是不一樣型號的計算機其機器語言是不相通的,按着一種計算機的機器指令編制的程序,不能在另外一種計算機上執行。面試

由於機器語言是使用二進制表示的,因此編出的程序全是些0和1的指令代碼。算法

機器語言的優勢就是能夠直接被計算機識別和執行,比較高效,可是同時也有不少缺點,如:編程

  • 一、機器只認識0和1,程序員很難記住每一個指令轉成0和1的組合是什麼,須要查大量的表格來肯定每一個數字表示什麼意思後端

  • 二、由於它的書面形式全是"密"碼,因此可讀性差,不便於交流與合做。

  • 三、由於它嚴重地依賴於具體的計算機,因此可移植性差,重用性差。

因爲機器語言有這麼多的弊端,因而有了彙編語言。

彙編語言

彙編語言使用助記符(Mnemonics)來代替和表示特定低級機器語言的操做。

助記符(mnemonic)是便於人們記憶、並能描述指令功能和指令操做數的符號,助記符是代表指令功能的英語單詞或其縮寫。如用ADD表示加法、MOV表示傳送、SUB表示減法等。

可是,彙編語言只是讓使用者,即程序員們更加容易記住和使用,計算機並不認識彙編語言,因此,想要讓計算機執行彙編代碼,須要先將彙編程序將它們轉換成可執行的機器語言代碼。這一過程被稱爲彙編過程。

因爲彙編更接近機器語言,可以直接對硬件進行操做,生成的程序與其餘的語言相比具備更高的運行速度,佔用更小的內存,所以在一些對於時效性要求很高的程序、許多大型程序的核心模塊以及工業控制方面大量應用。

機器語言和彙編語言,兩者是幾乎不多或者徹底沒有作任何語法抽象的,這種語言咱們一般稱之爲低級語言,這種更加接近硬件,並且是不能夠在不一樣硬件間移植的。

可是隨着現代軟件系統愈來愈龐大複雜,大量通過了封裝的高級語言如C/C++,Pascal/Object Pascal也應運而生。這些新的語言使得程序員在開發過程當中可以更簡單,更有效率,使軟件開發人員得以應付快速的軟件開發的要求。

高級語言

高級語言是高度封裝了的編程語言,與低級語言相對。

它是以人類的平常語言爲基礎的一種編程語言,使用通常人易於接受的文字來表示(例如漢字、不規則英文或其餘外語),從而使程序編寫員編寫更容易,亦有較高的可讀性,以方便對電腦認知較淺的人亦能夠大概明白其內容。

如流行的java,c,c++,C#,pascal,python,lisp,prolog,FoxPro,易語言,中文版的C語言習語言等等,這些語言的語法、命令格式都不相同。

同彙編語言同樣,高級語言離機器語言更加遠了,計算機沒法直接誒識別高級語言。因此,想要讓計算機執行高級語言,就須要將其轉化爲機器語言。

程序設計語言從機器語言到高級語言的抽象,帶來的主要好處主要有如下幾個方面:

 

  • 一、高級語言接近算法語言,易學、易掌握,通常工程技術人員只要幾周時間的培訓就能夠勝任程序員的工做;

  • 二、高級語言爲程序員提供告終構化程序設計的環境和工具,使得設計出來的程序可讀性好,可維護性強,可靠性高;

  • 三、高級語言遠離機器語言,與具體的計算機硬件關係不大,於是所寫出來的程序可移植性好,重用率高;

  • 四、因爲把繁雜瑣碎的事務交給了編譯程序去作,因此自動化程度高,開發週期短,且程序員獲得解脫,能夠集中時間和精力去從事對於他們來講更爲重要的創造性勞動,以提升程序的質量。

 

編譯

上面提到語言有兩種,一種低級語言,一種高級語言。能夠這樣簡單的理解:低級語言是計算機認識的語言、高級語言是程序員認識的語言。

那麼,怎麼把程序員寫出來的高級語言轉換成計算機認識的低級語言而後讓計算機執行呢?

這個過程其實就是編譯!

編譯的主要的目的是將便於人編寫、閱讀、維護的高級語言所寫做的源代碼程序,翻譯爲計算機能解讀、運行的低級語言的程序,也就是可執行文件。

Java語言的編譯

Java語言做爲一種高級語言,想要被執行,就須要經過編譯的手段將其轉換爲機器語言。

Java語言的源文件是一個java文件,要將一個java文件,轉換爲二進制文件一共要通過兩個步驟。

首先通過前端編譯器,將java文件編譯成中間代碼,這種中間代碼就是class文件,即字節碼文件。

而後,在通過後端編譯器,將class字節碼文件,編譯成機器語言。

Java的前端編譯器主要是javac, Eclipse JDT 中的增量式編譯器 ECJ 等。

Java的後端編譯器主要是各大虛擬機實現的,如HotSpot中的JIT編譯器。

反編譯

前面講過,咱們能夠經過編譯器,把高級語言的源代碼編譯成低級語言,那麼反之,咱們亦能夠經過低級語言進行反向工程,獲取其源代碼。這個過程,就叫作反編譯。

咱們雖然很難將機器語言反編譯成源代碼,可是,咱們仍是能夠把中間代碼進行反編譯的。就像咱們雖然不能把通過虛擬機編譯後的機器語言進行反編譯,可是咱們把javac編譯獲得的class進行反編譯仍是可行的。

因此,咱們說Java的反編譯,通常是將class文件轉換成java文件。

反編譯的做用

首先,反編譯對於學習Java來講是一個很好的手段。

由於Java做爲一種編程語言,提供了不少語法糖,如泛型、自動裝箱與拆箱等,而這些語法糖Java虛擬機是不認識的,因此在javac編譯的時候,就會進行解糖,而獲得的class文件中就是解糖後的代碼,這時候咱們把這種解糖後的class文件進行反編譯,就能夠獲得一份java文件,從這份java文件中,咱們就能夠學習到這些語法糖究竟是如何實現的。

其次,有了反編譯的工具,咱們就能夠把別人的代碼進行反編譯,而後學習別人的代碼是怎麼實現的。或者能夠經過源代碼查找bug,製做外掛等。

反編譯的工具

Java中有不少反編譯工具,這裏簡單介紹幾種

javap

javap是jdk自帶的一個工具,能夠對代碼反編譯,也能夠查看java編譯器生成的字節碼。javap生成的文件並非java文件,而是程序員能夠看得懂的class字節碼文件。

jad

jad是一個比較不錯的反編譯工具,只要下載一個執行工具,就能夠實現對class文件的反編譯了。

jad是能夠把class文件反編譯成java文件的。

可是,jad已經好久不更新了,在對Java7生成的字節碼進行反編譯時,偶爾會出現不支持的問題,在對Java 8的lambda表達式反編譯時就完全失敗。

地址:http://www.javadecompilers.com/jad

CFR

jad很好用,可是好久沒更新了,因此只能用一款新的工具替代他,CFR是一個不錯的選擇,相比jad來講,他的語法可能會稍微複雜一些,可是好在他能夠work。

地址:http://www.benf.org/other/cfr/index.html

JD-GUI

JD-GUI是一個獨立的圖形實用程序,顯示「.class」文件的Java源代碼。您可使用JD-GUI瀏覽重建的源代碼,以便當即訪問方法和字段。

如何防止反編譯

因爲咱們有工具能夠對Class文件進行反編譯,因此,對開發人員來講,如何保護Java程序就變成了一個很是重要的挑戰。

可是,魔高一尺、道高一丈。固然有對應的技術能夠應對反編譯。

可是,這裏仍是要說明一點,和網絡安全的防禦同樣,不管作出多少努力,其實都只是提升攻擊者的成本而已。沒法完全防治。

典型的應對策略有如下幾種:

  • 隔離Java程序,讓用戶接觸不到你的Class文件

  • 對Class文件進行加密,提到破po解jie難度

  • 代碼混淆,將代碼轉換成功能上等價,可是難於閱讀和理解的形式

如阿里巴巴開源的分佈式事務中間件的jar包就經過混淆技術進行了加密,反編譯後內容以下:

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息