Java代碼的編譯與反編譯那些事兒

編程語言

在介紹編譯和反編譯之前,我們先來簡單介紹下編程語言(Programming Language)。編程語言(Programming Language)分為低級語言(Low-level Language)和高級語言(High-level Language)猎醇。

機(jī)器語言(Machine Language)和匯編語言(Assembly Language)屬于低級語言窥突,直接用計(jì)算機(jī)指令編寫程序。

而C硫嘶、C++阻问、Java、Python等屬于高級語言沦疾,用語句(Statement)編寫程序称近,語句是計(jì)算機(jī)指令的抽象表示。

舉個(gè)例子哮塞,同樣一個(gè)語句用C語言刨秆、匯編語言和機(jī)器語言分別表示如下:

Java代碼的編譯與反編譯那些事兒

計(jì)算機(jī)只能對數(shù)字做運(yùn)算,符號忆畅、聲音衡未、圖像在計(jì)算機(jī)內(nèi)部都要用數(shù)字表示,指令也不例外家凯,上表中的機(jī)器語言完全由十六進(jìn)制數(shù)字組成缓醋。最早的程序員都是直接用機(jī)器語言編程,但是很麻煩绊诲,需要查大量的表格來確定每個(gè)數(shù)字表示什么意思送粱,編寫出來的程序很不直觀,而且容易出錯(cuò)掂之,于是有了匯編語言抗俄,把機(jī)器語言中一組一組的數(shù)字用助記符(Mnemonic)表示,直接用這些助記符寫出匯編程序世舰,然后讓匯編器(Assembler)去查表把助記符替換成數(shù)字动雹,也就把匯編語言翻譯成了機(jī)器語言。

但是跟压,匯編語言用起來同樣比較復(fù)雜洽胶,后面,就衍生出了Java裆馒、C、C++等高級語言丐怯。

什么是編譯

上面提到語言有兩種喷好,一種低級語言,一種高級語言读跷」=粒可以這樣簡單的理解:低級語言是計(jì)算機(jī)認(rèn)識的語言、高級語言是程序員認(rèn)識的語言。

那么如何從高級語言轉(zhuǎn)換成低級語言呢无切?這個(gè)過程其實(shí)就是編譯荡短。

從上面的例子還可以看出,C語言的語句和低級語言的指令之間不是簡單的一一對應(yīng)關(guān)系哆键,一條a=b+1;語句要翻譯成三條匯編或機(jī)器指令掘托,這個(gè)過程稱為編譯(Compile),由編譯器(Compiler)來完成籍嘹,顯然編譯器的功能比匯編器要復(fù)雜得多闪盔。用C語言編寫的程序必須經(jīng)過編譯轉(zhuǎn)成機(jī)器指令才能被計(jì)算機(jī)執(zhí)行,編譯需要花一些時(shí)間辱士,這是用高級語言編程的一個(gè)缺點(diǎn)泪掀,然而更多的是優(yōu)點(diǎn)。首先颂碘,用C語言編程更容易异赫,寫出來的代碼更緊湊,可讀性更強(qiáng)头岔,出了錯(cuò)也更容易改正塔拳。

將便于人編寫、閱讀切油、維護(hù)的高級計(jì)算機(jī)語言所寫作的源代碼程序蝙斜,翻譯為計(jì)算機(jī)能解讀、運(yùn)行的低階機(jī)器語言的程序的過程就是編譯澎胡。負(fù)責(zé)這一過程的處理的工具叫做編譯器

現(xiàn)在我們知道了什么是編譯孕荠,也知道了什么是編譯器。不同的語言都有自己的編譯器攻谁,Java語言中負(fù)責(zé)編譯的編譯器是一個(gè)命令:javac

javac是收錄于JDK中的Java語言編譯器稚伍。該工具可以將后綴名為.java的源文件編譯為后綴名為.class的可以運(yùn)行于Java虛擬機(jī)的字節(jié)碼。

當(dāng)我們寫完一個(gè)HelloWorld.java文件后戚宦,我們可以使用javac HelloWorld.java命令來生成HelloWorld.class文件个曙,這個(gè)class類型的文件是JVM可以識別的文件。通常我們認(rèn)為這個(gè)過程叫做Java語言的編譯受楼。其實(shí)垦搬,class文件仍然不是機(jī)器能夠識別的語言,因?yàn)闄C(jī)器只能識別機(jī)器語言艳汽,還需要JVM再將這種class文件類型字節(jié)碼轉(zhuǎn)換成機(jī)器可以識別的機(jī)器語言猴贰。

什么是反編譯

反編譯的過程與編譯剛好相反,就是將已編譯好的編程語言還原到未編譯的狀態(tài)河狐,也就是找出程序語言的源代碼米绕。就是將機(jī)器看得懂的語言轉(zhuǎn)換成程序員可以看得懂的語言瑟捣。Java語言中的反編譯一般指將class文件轉(zhuǎn)換成java文件。

有了反編譯工具栅干,我們可以做很多事情迈套,最主要的功能就是有了反編譯工具,我們就能讀得懂Java編譯器生成的字節(jié)碼碱鳞。如果你想問讀懂字節(jié)碼有啥用桑李,那么我可以很負(fù)責(zé)任的告訴你,好處大大的劫笙。比如我的博文幾篇典型的原理性文章芙扎,都是通過反編譯工具得到反編譯后的代碼分析得到的。如深入理解多線程(一)——Synchronized的實(shí)現(xiàn)原理填大、深度分析Java的枚舉類型—-枚舉的線程安全性及序列化問題戒洼、Java中的Switch對整型、字符型允华、字符串型的具體實(shí)現(xiàn)細(xì)節(jié)圈浇、Java的類型擦除等。我最近在GitChat寫了一篇關(guān)于Java語法糖的文章靴寂,其中大部分內(nèi)容都用到反編譯工具來洞悉語法糖背后的原理磷蜀。

Java反編譯工具

本文主要介紹3個(gè)Java的反編譯工具:javapjadcfr

javap

javap是jdk自帶的一個(gè)工具百炬,可以對代碼反編譯褐隆,也可以查看java編譯器生成的字節(jié)碼。javap和其他兩個(gè)反編譯工具最大的區(qū)別是他生成的文件并不是java文件剖踊,也不像其他兩個(gè)工具生成代碼那樣更容易理解庶弃。拿一段簡單的代碼舉例,如我們想分析Java 7中的switch是如何支持String的德澈,我們先有以下可以編譯通過的源代碼:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public class switchDemoString {
public static void main(String[] args) {
String str = "world";
switch (str) {
case "hello":
System.out.println("hello");
break;
case "world":
System.out.println("world");
break;
default:
break;
}
}
}
復(fù)制代碼
</pre>

執(zhí)行以下兩個(gè)命令:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">javac switchDemoString.java
javap -c switchDemoString.class
復(fù)制代碼
</pre>

生成代碼如下:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public class com.hollis.suguar.switchDemoString {
public com.hollis.suguar.switchDemoString();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String world
2: astore_1
3: aload_1
4: astore_2
5: iconst_m1
6: istore_3
7: aload_2
8: invokevirtual #3 // Method java/lang/String.hashCode:()I
11: lookupswitch { // 2
99162322: 36
113318802: 50
default: 61
}
36: aload_2
37: ldc #4 // String hello
39: invokevirtual #5 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
42: ifeq 61
45: iconst_0
46: istore_3
47: goto 61
50: aload_2
51: ldc #2 // String world
53: invokevirtual #5 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
56: ifeq 61
59: iconst_1
60: istore_3
61: iload_3
62: lookupswitch { // 2
0: 88
1: 99
default: 110
}
88: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
91: ldc #4 // String hello
93: invokevirtual #7 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
96: goto 110
99: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
102: ldc #2 // String world
104: invokevirtual #7 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
107: goto 110
110: return
}
復(fù)制代碼
</pre>

我個(gè)人的理解歇攻,javap并沒有將字節(jié)碼反編譯成java文件,而是生成了一種我們可以看得懂字節(jié)碼梆造。其實(shí)javap生成的文件仍然是字節(jié)碼缴守,只是程序員可以稍微看得懂一些。如果你對字節(jié)碼有所掌握镇辉,還是可以看得懂以上的代碼的屡穗。其實(shí)就是把String轉(zhuǎn)成hashcode,然后進(jìn)行比較忽肛。

個(gè)人認(rèn)為鸡捐,一般情況下我們會(huì)用到j(luò)avap命令的時(shí)候不多,一般只有在真的需要看字節(jié)碼的時(shí)候才會(huì)用到麻裁。但是字節(jié)碼中間暴露的東西是最全的,你肯定有機(jī)會(huì)用到,比如我在分析synchronized的原理的時(shí)候就有是用到j(luò)avap煎源。通過javap生成的字節(jié)碼色迂,我發(fā)現(xiàn)synchronized底層依賴了ACC_SYNCHRONIZED標(biāo)記和monitorenter、monitorexit兩個(gè)指令來實(shí)現(xiàn)同步手销。

jad

jad是一個(gè)比較不錯(cuò)的反編譯工具歇僧,只要下載一個(gè)執(zhí)行工具,就可以實(shí)現(xiàn)對class文件的反編譯了锋拖。還是上面的源代碼诈悍,使用jad反編譯后內(nèi)容如下:

命令:jad switchDemoString.class

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public class switchDemoString
{
public switchDemoString()
{
}
public static void main(String args[])
{
String str = "world";
String s;
switch((s = str).hashCode())
{
default:
break;
case 99162322:
if(s.equals("hello"))
System.out.println("hello");
break;
case 113318802:
if(s.equals("world"))
System.out.println("world");
break;
}
}
}
復(fù)制代碼
</pre>

看,這個(gè)代碼你肯定看的懂兽埃,因?yàn)檫@不就是標(biāo)準(zhǔn)的java的源代碼么侥钳。這個(gè)就很清楚的可以看到原來字符串的switch是通過equals()和hashCode()方法來實(shí)現(xiàn)的

但是柄错,jad已經(jīng)很久不更新了舷夺,在對Java7生成的字節(jié)碼進(jìn)行反編譯時(shí),偶爾會(huì)出現(xiàn)不支持的問題售貌,在對Java 8的lambda表達(dá)式反編譯時(shí)就徹底失敗给猾。

CFR

jad很好用,但是無奈的是很久沒更新了颂跨,所以只能用一款新的工具替代他敢伸,CFR是一個(gè)不錯(cuò)的選擇,相比jad來說恒削,他的語法可能會(huì)稍微復(fù)雜一些池颈,但是好在他可以work。

如蔓同,我們使用cfr對剛剛的代碼進(jìn)行反編譯饶辙。執(zhí)行一下命令:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">java -jar cfr_0_125.jar switchDemoString.class --decodestringswitch false
復(fù)制代碼
</pre>

得到以下代碼:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public class switchDemoString {
public static void main(String[] arrstring) {
String string;
String string2 = string = "world";
int n = -1;
switch (string2.hashCode()) {
case 99162322: {
if (!string2.equals("hello")) break;
n = 0;
break;
}
case 113318802: {
if (!string2.equals("world")) break;
n = 1;
}
}
switch (n) {
case 0: {
System.out.println("hello");
break;
}
case 1: {
System.out.println("world");
break;
}
}
}
}
復(fù)制代碼
</pre>

通過這段代碼也能得到字符串的switch是通過equals()和hashCode()方法來實(shí)現(xiàn)的結(jié)論。

相比Jad來說斑粱,CFR有很多參數(shù)弃揽,還是剛剛的代碼,如果我們使用以下命令则北,輸出結(jié)果就會(huì)不同:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">java -jar cfr_0_125.jar switchDemoString.class
public class switchDemoString {
public static void main(String[] arrstring) {
String string;
switch (string = "world") {
case "hello": {
System.out.println("hello");
break;
}
case "world": {
System.out.println("world");
break;
}
}
}
}
復(fù)制代碼
</pre>

所以--decodestringswitch表示對于switch支持string的細(xì)節(jié)進(jìn)行解碼矿微。類似的還有--decodeenumswitch、--decodefinally尚揣、--decodelambdas等涌矢。在我的關(guān)于語法糖的文章中,我使用--decodelambdas對lambda表達(dá)式警進(jìn)行了反編譯快骗。 源碼:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public static void main(String... args) {
List<String> strList = ImmutableList.of("Hollis", "公眾號:Hollis", "博客:www.hollischuang.com");
strList.forEach( s -> { System.out.println(s); } );
}
復(fù)制代碼
</pre>

java -jar cfr_0_125.jar lambdaDemo.class --decodelambdas false反編譯后代碼:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public static /* varargs / void main(String ... args) {
ImmutableList strList = ImmutableList.of((Object)"Hollis", (Object)"\u516c\u4f17\u53f7\uff1aHollis", (Object)"\u535a\u5ba2\uff1awww.hollischuang.com");
strList.forEach((Consumer<String>)LambdaMetafactory.metafactory(null, null, null, (Ljava/lang/Object;)V, lambdamain0(java.lang.String ), (Ljava/lang/String;)V)());
}
private static /
synthetic */ void lambdamain0(String s) {
System.out.println(s);
}
復(fù)制代碼
</pre>

CFR還有很多其他參數(shù)娜庇,均用于不同場景塔次,讀者可以使用java -jar cfr_0_125.jar --help進(jìn)行了解。這里不逐一介紹了名秀。

如何防止反編譯

由于我們有工具可以對Class文件進(jìn)行反編譯励负,所以,對開發(fā)人員來說匕得,如何保護(hù)Java程序就變成了一個(gè)非常重要的挑戰(zhàn)继榆。但是,魔高一尺汁掠、道高一丈略吨。當(dāng)然有對應(yīng)的技術(shù)可以應(yīng)對反編譯咯。但是考阱,這里還是要說明一點(diǎn)翠忠,和網(wǎng)絡(luò)安全的防護(hù)一樣,無論做出多少努力羔砾,其實(shí)都只是提高攻擊者的成本而已负间。無法徹底防治。

典型的應(yīng)對策略有以下幾種:

  • 隔離Java程序
  • 讓用戶接觸不到你的Class文件
  • 對Class文件進(jìn)行加密
  • 提到破解難度
  • 代碼混淆
  • 將代碼轉(zhuǎn)換成功能上等價(jià)姜凄,但是難于閱讀和理解的形式
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末政溃,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子态秧,更是在濱河造成了極大的恐慌董虱,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件申鱼,死亡現(xiàn)場離奇詭異愤诱,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)捐友,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進(jìn)店門淫半,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人匣砖,你說我怎么就攤上這事科吭。” “怎么了猴鲫?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵对人,是天一觀的道長。 經(jīng)常有香客問我拂共,道長牺弄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任宜狐,我火速辦了婚禮势告,結(jié)果婚禮上蛇捌,老公的妹妹穿的比我還像新娘。我一直安慰自己培慌,他們只是感情好豁陆,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著吵护,像睡著了一般。 火紅的嫁衣襯著肌膚如雪表鳍。 梳的紋絲不亂的頭發(fā)上佣蓉,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天覆劈,我揣著相機(jī)與錄音,去河邊找鬼。 笑死书蚪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的嘲恍。 我是一名探鬼主播嘀趟,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼绳姨!你這毒婦竟也來了登澜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤飘庄,失蹤者是張志新(化名)和其女友劉穎脑蠕,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體跪削,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谴仙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了碾盐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晃跺。...
    茶點(diǎn)故事閱讀 38,654評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖毫玖,靈堂內(nèi)的尸體忽然破棺而出掀虎,到底是詐尸還是另有隱情,我是刑警寧澤孕豹,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布涩盾,位于F島的核電站,受9級特大地震影響励背,放射性物質(zhì)發(fā)生泄漏春霍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一叶眉、第九天 我趴在偏房一處隱蔽的房頂上張望址儒。 院中可真熱鬧芹枷,春花似錦、人聲如沸莲趣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽喧伞。三九已至走芋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間潘鲫,已是汗流浹背翁逞。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留溉仑,地道東北人挖函。 一個(gè)月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像浊竟,于是被迫代替她去往敵國和親怨喘。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內(nèi)容

  • 編譯 編程語言有高級和低級之分振定。所謂低級語言就是指可以被計(jì)算機(jī)理解并執(zhí)行的語言必怜,例如機(jī)器語言。而高級語言計(jì)算...
    still_loving閱讀 1,729評論 0 4
  • Java的編譯和反編譯 什么是編譯 編譯就是把C吩案、C++棚赔、Java等高級語言轉(zhuǎn)換成匯編語言、機(jī)器語言等低級語言的過...
    人在碼途閱讀 5,896評論 0 2
  • 第一章 初識javaJAVA 第一講:什么是程序?:為了讓計(jì)算機(jī)執(zhí)行某些操作或解決某個(gè)問題而編寫的一系列有序指令的...
    人子日月幾點(diǎn)閱讀 510評論 0 1
  • 只能用于一種evet下徘郭,如果為兩種evet使用會(huì)出現(xiàn)覆蓋靠益,執(zhí)行后關(guān)聯(lián)的block
    Zhui_Do閱讀 285評論 0 2
  • 最近看到一句話,讓我印象深刻残揉,大意是“有很多人不會(huì)蒙著眼睛過馬路胧后,卻會(huì)蒙著眼睛過人生”。是呀抱环,人們在過馬路...
    六邁神踐閱讀 353評論 0 0