日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

看到一个沙粒世界:再一次你好世界

發布時間:2023/12/3 编程问答 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 看到一个沙粒世界:再一次你好世界 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

“看到一個沙粒中的世界”,我們很可能會看到最簡單的“ Hello World”中的世界,所以我們開始吧,再一次向世界問好。

我猜所有的Java課程,教程都是從這個著名的Hello World程序開始的,這是我可以在沒有IDE的幫助下編寫的非常罕見的程序之一:)

public class HelloWorld {public static void main(String[] args) {System.out.println("Hello World");} }

1.您知道這些javac選項嗎?

編寫第一個程序后,您將首先執行以下命令進行編譯,否則將無法運行。

javac HelloWorld.java

您可能會發現不必將文件命名為“ HelloWorld.java”,“ Hello.java”也可以使用。 public class HelloWorld也可以降級為class HelloWorld 。

如果您好奇地按下javac --help ,將會看到很多有關Java編譯器的選項,例如,我們要打印中文版“ Hello World”,并希望它完全適用于JDK8語言級別,元數據為包含的參數名稱,它看起來像這樣:

javac -encoding UTF-8 -source 8 -target 8 -parameters Hello.java

您已經安裝了JDK11,但是使用上面的命令僅使用1.8功能發布了類文件。 如果您編寫了一些僅可從JDK9獲得的內容,則會發現它無法按預期進行編譯。

2.類文件的基礎

關于Java虛擬機規范中的類文件格式的整章內容,您是否需要對其進行一些探討?

您會看到字節碼(與JDK11一起編譯)以一個神奇的,神秘的“ cafe babe”開頭,隨后為55,很多東西會傷害您的大腦。 其中,“ cafe babe”是魔力,指向次要版本的55分,映射到JDK11。 與讀取超贊的類文件格式相比,您還可以使用javap檢索該類文件的信息:

# You would use javap -h to see how many options you have javap -p -l -c -s -constants HelloWorld

您將獲得如下內容:

class HelloWorld {HelloWorld(); descriptor: ()V Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 1: 0 public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V Code: 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3 // String Hello World 5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V8: return LineNumberTable: line 4: 0 line 5: 8 }

您會發現這里的指令與源代碼有些相似,帶有源代碼的行號和指令號的映射,您可能想知道,我可以從這些東西中恢復源代碼嗎?

3.反編譯器

是的你可以。 反編譯器有很多,但是其中一些反編譯器已經過時,例如JD-GUI ,JAD等,它們在使用最新JDK編譯的類文件上不能很好地工作。 您仍然可以使用它們,但CFR更合適。

# java -jar cfr-0.139.jar HelloWorld.class /* * Decompiled with CFR 0.139.*/ import java.io.PrintStream; class HelloWorld { HelloWorld() { } public static void main(String[] arrstring) {System.out.println("Hello World"); } }

您可能已經發現源代碼和反編譯的代碼(添加了構造方法)略有不同,實際上,您可能會驚訝地發現有時似乎對源代碼進行了修改,從而使您感到驚訝。 但是,其中許多是通過JVM進行的優化,通常可以提高性能,比較它們之間的差異實際上很有趣,并且可以為您提供很多見識。

4.如何再次初始化具有空值的最終變量?

System.out.println("Hello World") ,System是一個類,out是其最終屬性的靜態屬性之一:

public final static PrintStream out = null;

然后問題來了,為什么hack System.out.println("Hello World")不會拋出著名的NullPointerException ,根據語言規范,似乎最終的靜態變量out不可能分配給有效值再次吧?

是的,在大多數情況下,如果您不使用骯臟的反射技巧并且不引入native好友,那是對的。

如果您只是想玩轉,可以這樣做:

Field f = clazz.getDeclaredField("out"); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL);

但是,這對于System無效,實際的秘密隱藏在System.java以下代碼行中:

private static native void registerNatives(); static {registerNatives(); }

按照方法上方寫的注釋,“ VM將調用initializeSystemClass方法來完成此類的初始化”,轉到initializeSystemClass方法,您將看到以下行:

FileInputStream fdIn = new FileInputStream(FileDescriptor.in); FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out); FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err); setIn0(new BufferedInputStream(fdIn)); setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding"))); setErr0(newPrintStream(fdErr, props.getProperty("sun.stderr.encoding")));

而且你還可以看到這3種本地方法設置in與out :

private static native void setIn0(InputStream in); private static native void setOut0(PrintStream out); private static native void setErr0(PrintStream err);

因此,現在您知道JVM在OS級別上做了這些工作并“繞過”了final限制,您可能會問,JVM將適應的OS級別代碼在哪里被破解?

所以這里是System.c (JDK11版本) 。

JNIEXPORT void JNICALL Java_java_lang_System_registerNatives(JNIEnv *env, jclass cls) {(*env)->RegisterNatives(env, cls,methods, sizeof(methods)/sizeof(methods[0])); } /** The following three functions implement setter methods for* java.lang.System.{in, out, err}. They are natively implemented* because they violate the semantics of the language (i.e. set final* variable).*/ JNIEXPORT void JNICALL Java_java_lang_System_setIn0(JNIEnv *env, jclass cla, jobject stream) {jfieldID fid =(*env)->GetStaticFieldID(env,cla,"in","Ljava/io/InputStream;");if (fid == 0)return;(*env)->SetStaticObjectField(env,cla,fid,stream); }

在這里,您可以在注釋中找到后門, “它們是本機實現的,因為它們違反了語言的語義(即,設置最終變量)” 。

然后,您會發現這是一條漫長的道路。 旅程將永遠不會停止。

結束:停一會兒

“用沙粒看世界
還有野花中的天堂
將Infinity握在手中 一小時的永恒”

如果最簡單的HelloWorld只是一片沙粒,那么里面肯定有一個世界,也許您對它說過很多次“ Hello”,但這并不意味著您已經探索了一點世界,也許現在時間和探索世界,雖然沙子會使您的手變臟,但花朵卻不會。

翻譯自: https://www.javacodegeeks.com/2019/02/world-grain-sand-world.html

總結

以上是生活随笔為你收集整理的看到一个沙粒世界:再一次你好世界的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。