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

“看到一个沙粒中的世界”,我们很可能会看到最简单的“ 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种本地方法设置inout

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/344298.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[渝粤教育] 西南科技大学 中国现代文学 在线考试复习资料

中国现代文学——在线考试复习资料 一、单选题 1.不属于“五四”时期的“问题小说”作家的是( )。 A.冰心 B.庐隐 C.刘呐鸥 D.王统照 2.巴金小说《家》中的觉新是( )。 A.顽固的封建卫道者 B.腐朽堕落者 C.有新思想的懦弱者 D.与封建思想大胆斗争的反抗者 3.《画梦录》的作者…

[渝粤教育] 西南科技大学 中学英语教材教法 在线考试复习资料

中学英语教材教法——在线考试复习资料 一、单选题 1.关于写作评估以下说法正确的是? A.写作评估既要有结果评估,也要有过程评估 B.写作教学评估有写长法又有写短法 C.课堂评估的作用仅为监控学生 D.课堂评估与课堂的具体教学内容有关,可以使用统一的评估模式 2.以下哪种方式…

moreunit_MoreUnit与MoreUnit

moreunit就在一年多以前&#xff0c;我写了一篇关于在Eclipse中使用JUnit的文章。 评论者之一推荐MoreUnit &#xff0c;以进一步提高测试效率。 尝试一下让我感到很高兴&#xff0c;并且我的自主神经系统立即记住了该插件的键盘快捷键…… 另外&#xff0c;在使用MoreUnit一段…

[渝粤教育] 西南科技大学 人力资源管理 在线考试复习资料(1)

人力资源管理——在线考试复习资料 一、单选题 1.实施工作轮换方案之前要做好的工作不包括( ) A.复查每一个连续在同一职业岗位上于了5年以上.特别是更长时间的、正处于职业中期的员工(包括经理在内) 的人事文件 B.评价这些员工的工作,认清其工作专长,了解其个人特征、才干等 C…

android 获取 meid 代码,Android 各个版本获取IMEI、MEID

public class IMEIUtil {/*** 获取默认的imei 一般都是IMEI 1** param context* return*/public static String getIMEI1(Context context) {//优先获取IMEI(即使是电信卡) 不行的话就获取MEIDreturn getImeiOrMeid(context, 0);}/*** 获取imei2** param context* return*/publ…

JMetro版本5发布

Java的第5版JavaFX主题JMetro刚刚发布。 这是此版本中的新功能&#xff1a; 新的文本区域明暗风格&#xff1b; 现有控件样式的一些更改&#xff1b; 新CSS变量称为accent_color。 顾名思义&#xff0c;它允许您定义JMetro控件中使用的强调颜色。 已经进行了很大的重构&am…

[渝粤教育] 西南科技大学 会计学原理 在线考试复习资料(1)

会计学原理——在线考试复习资料 一、单选题 1.资产负债表是反映企业( )财务状况的会计报表。 A.某一特定日期 B.一定时期内 C.某一月份内 D.某一年份内 2.某企业本期盘亏的材料已查明原因,属于自然损耗,批准处理时应编制的会计分录( )。 A.借记“待处理财产损溢”,…

android 开发 矩形截屏插件,Android 上如何实现矩形区域截屏

对屏幕进行截屏并裁剪有两种方式&#xff1a;早截图和晚截图。早截图&#xff0c;就是先截取全屏&#xff0c;再让用户对截取到的图片进行修改;与之相对的&#xff0c;晚截图&#xff0c;就是先让用户在屏幕上划好区域&#xff0c;再进行截图和裁剪。其实两者并没有什么太大的区…

[渝粤教育] 西南科技大学 供应链管理 在线考试复习资料

供应链管理——在线考试复习资料 一、单选题 1.人们设置库存的目的,不包括以下哪种? A.增加固定资产 B.防止缺货 C.保持生产连续性 D.快速满足订货需求 2.费希尔(Fisher)按市场需求模式将产品分为两类,即功能性产品和创新性产品。下面属于功能性产品的是: A.时装 B.石油 C.手…

[渝粤教育] 西南科技大学 信息组织与检索 在线考试复习资料2021版

信息组织与检索——在线考试复习资料2021版 一、单选题 1.要求两个关键词至少有一个出现在检索结果中需使用的操作符是( )。 A. ND B. OR C. ND NOT D. NEAR 答案:看左边查询 2.要求两个关键词都必须出现在检索结果中需使用的操作符是( )。 A. ND B. OR C. ND NOT D. NE…

Android布局怎么画图形,Android开发者的图形化布局

图形化布局编辑器允许你通过拖放来创建UI。在早期版本的ADT中&#xff0c;图形化布局编辑器并不是很有帮助&#xff0c;幸运的是&#xff0c;最新版本非常强大&#xff0c;可以用来创建复杂的包含有复合组件以及动画的布局。(1)Configuration下拉菜单让你可以改变当前布局展示的…

java注释类型_Java 8类型注释

java注释类型Lambda表达式是迄今为止Java 8讨论最多和最受促进的功能。虽然我同意Lambda是一个很大的改进&#xff0c;但我认为其他一些Java 8功能由于Lambda的炒作而有所欠缺。 在这篇文章中&#xff0c;我想展示另一个来自Java 8的出色特性的示例&#xff1a;Type Annotation…

[渝粤教育] 西南科技大学 公共组织学 在线考试复习资料

公共组织学——在线考试复习资料 一、单选题 1.从沟通媒介自身的丰富性程度看,排在第一位的应该是( ) A.电话 B.电子邮件 C.面对面地交谈 D.文件 2.“韦伯认为,以古老的传统、神圣不可侵犯的信念,以及对其下属行使权力的人的地位的合法性为基础的权力属于( ) A.合理–合法型…

[渝粤教育] 西南科技大学 刑事诉讼法学 在线考试复习资料

刑事诉讼法学——在线考试复习资料 一、单选题 1.传唤、拘传持续的时间不得超过十二小时;案情特别重大、复杂,需要采取拘留、逮捕措施的,传唤、拘传持续的时间不得超过( )小时。 A.12 B.24 C.48 2.无期徒刑的执行机关是?( ) A.公安机关 B.监狱 C.检察机关 D.人民法院 3.讯问…

android studio简易记账本,Android记账本

十分感谢徐老师用心制作的这个视频&#xff0c;我学到了很多&#xff0c;再次感谢。这里贴一下我对着这个视频写的代码&#xff1a;https://github.com/supertian007/ImoocDaily&#xff0c;欢迎大家参考、或指出问题。记录一下学习过程中遇到的几个问题&#xff1a;1. 视频的b…

Java可选参数

在Java类中设计方法时&#xff0c;某些参数对于其执行而言可能是可选的。 无论是在DTO&#xff0c;胖模型域对象还是简单的无状态服务类中&#xff0c;可选方法参数都是常见的。 从本文中&#xff0c; 您将学习如何在Java中处理可选参数 。 我们将专注于常规方法&#xff0c;带…

[渝粤教育] 西南科技大学 单片机原理与应用 在线考试复习资料(2)

单片机原理与应用——在线考试复习资料 一、单选题 1.信息能够同时双向传送的是( )。 A.并行通信 B.单工串行通信 C.半双工串行通信 D.全双工串行通信 2.T89S52单片机片内有( )个定时器/计数器。 A.1 B.2 C.3 D.4 3.串口通信时,每秒传送120个字符,数据格式为1位起始位、8位数…

android前台进程视频教程,Android Twilio视频通话,唤醒应用程序并进入前台

因此,我们已经找到了解决方案(当收到通知时,将应用程序置于前台),即使已经有一段时间了,我仍在发布它&#xff1a;> FCM通知(firebase云消息传递通知)只需在通知中发送“数据”.因此,通知的JSON结构中没有Notification对象,只有数据.这样,通知便由您应用的FirebaseMessaging…

[渝粤教育] 西南科技大学 土木工程施工 在线考试复习资料(1)

土木工程施工——在线考试复习资料 一、单选题 1.先张法预应力筋放张时,其混凝土应到达设计强度的( )。 A.50% B.75% C.90% D.100% 2.抹灰标志块的厚度为( )。 A.底层厚度 B.中层厚度 C.底层中层厚度 D.底层中层面层厚度 3.预应力超张拉是为了( )。 A.减少预应力筋与孔道摩擦…

[渝粤教育] 西南科技大学 审计原理与实务 在线考试复习资料2021

审计原理与实务——在线考试复习资料2021 一、单选题 1. 注册会计师在执行报表审计业务中,若发现有违法行为,应当予以( )。 A.向主管部门报告 B.拒绝审计 C.向法院起诉 D.向董事会报告 答案:看左边查询 2.注册会计师从1000个应收账款明细账…