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

“看到一个沙粒中的世界”,我们很可能会看到最简单的“ 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,一经查实,立即删除!

相关文章

moreunit_MoreUnit与MoreUnit

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

JMetro版本5发布

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

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

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

Java可选参数

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

计算机发送到桌面快捷方式,windows7添加到桌面快捷方式无故消失!

您好&#xff0c;Windows 7设计者在Windows 7中所添加的设计。在默认情况下&#xff0c;只要System Maintenance troubleshooter(系统故障维护&#xff0c;以下简称SMT)检测到桌面的快捷方式已经无效了&#xff0c;将会自动将其删除。每周&#xff0c;SMT(系统故障维护)都会对操…

Java:汇总堆外数据

探索如何以最小的垃圾收集影响和最大的内存利用率创建堆​​外聚合。 使用Java Map&#xff0c;List和Object创建大型聚合通常会产生大量堆内存开销。 这也意味着&#xff0c;一旦聚合超出范围&#xff0c;垃圾收集器将必须清理这些对象。 阅读这篇简短的文章&#xff0c;了解…

java中属性外部化_用Java可外部化

java中属性外部化在理解Externalizable接口之前&#xff0c;您需要了解序列化。您可以在java中的序列化上阅读有关序列化的更多信息。 Java提供了一种称为序列化的机制&#xff0c;以按字节的有序或字节序列的形式持久化Java对象&#xff0c;其中包括对象的数据以及有关对象的…

在您的Maven-Fu包中增加了一些东西

Apache Maven很简单&#xff0c;但是功能非常强大。 使用一些技巧&#xff0c;您可以大大简化和优化您的开发经验。 处理多个非托管模块 假设您有一个主项目A提供了两个实用程序模块foo和bar &#xff0c;另一个项目B A了foo和bar 。 在使用B &#xff0c;您意识到需要偶尔对…

ci 邮件 html模板,CI Email类发邮件

发邮件代码详情private function _send_mail($data) {//附件一&#xff0c;名称参数编码转换if(!empty($data[resume_name])){$file_name iconv(UTF-8,GB2312,$data[file_name]);}//附件二&#xff0c;名称参数编码转换if(!empty($data[resume_name])){$resume_name iconv(UT…

Java安全动画

总览 自从JDK 1.2中引入安全沙箱模型以及JDK提供的安全API的发展以来&#xff0c;Java安全就一直是一个复杂的话题。 并发实用程序也观察到类似的问题&#xff0c;并且开发了一种名为Java Concurrent Animated的工具&#xff0c;目的是通过有趣而有趣的方式降低进入这些实用程序…

在计算机网络系统的远程通信中,在计算机网络系统的远程通信中,通常采用的传输技术是...

摘要&#xff1a;算机体系体系模板模板最适宜采用的合钢是组。系统信中民主命叙主义关于革命以下义革误的和社会主述错是(。程通常采传输不属民主主义济纲的三大经以下于新领的是(。...算机体系体系模板模板最适宜采用的合钢是组。网络不属特殊国无级自的是产阶以下于中有的优点…

ajax div 赋值重新渲染_优化向:单页应用多路由预渲染指南

前言Ajax 技术的出现&#xff0c;让我们的 Web 应用能够在不刷新的状态下显示不同页面的内容&#xff0c;这就是单页应用。在一个单页应用中&#xff0c;往往只有一个 html 文件&#xff0c;然后根据访问的 url 来匹配对应的路由脚本&#xff0c;动态地渲染页面内容。单页应用在…

fpga运算服务器_一张图了解CPU、GPU、ASIC、FPGA性能、功耗效率、灵活性

​CPU&#xff1a;中央处理器&#xff08;Central Processing Unit&#xff0c;CPU&#xff09;&#xff1a;通用芯片&#xff0c;主要生产厂家如intel、AMD等&#xff0c;用于PC、服务器等领域。CPU作为通用芯片&#xff0c;可以用来做很多事情&#xff0c;灵活性最高&#xf…

aspen变压吸附塔_空压机科普:吸附式干燥机的结构和原理

精彩内容本文以主流的“变压吸附式”干燥机为例进行讲解。“吸附”原理一致&#xff0c;“脱附再生”流程有所区别。从而大致形成以下几种常见类型&#xff1a;●无热吸附式——使用一部分经过干燥后的压缩空气&#xff0c;经降压后吹扫吸附剂&#xff0c;实现吸附剂“再生”&a…

小学计算机管理,小学计算机室管理制度

小学计算机室管理制度 (2页)本资源提供全文预览&#xff0c;点击全文预览即可全文预览,如果喜欢文档就下载吧&#xff0c;查找使用更方便哦&#xff01;19.90 积分芹菜小学计算机室制度1、计算机室由上电脑课老师负责管理。2、计算机室是进行电脑技术学习和操作的场所&#xff…

异形3×3魔方还原教程_【初级篇】(四)最简单的三阶魔方入门教程——中层还原...

本系列教程适合刚刚接触魔方&#xff0c;又比较有好奇心&#xff0c;是为渴望学会还原魔方&#xff0c;又不想死记公式的人准备的。全部教程只使用三种公式&#xff0c;还原过程以理解为主&#xff0c;公式为辅。第四部分 中层棱块还原4.1 预览中层棱块还原后的效果中层还原以后…

吞吐量-Corda的故事

我最近开展了一个针对特定用例的Corda性能项目。 这个项目的结果使我们在170多个节点的网络上一天之内处理了1.15亿个请求。 此外&#xff0c;Corda每秒能够处理6300个请求&#xff0c;确认满足了网络的最高要求。 迄今为止&#xff0c;这是迄今为止已部署的最大的Corda网络&am…

httpurlconnect设置中文参数_数控三菱CNC机床参数的设置及报警解除!

数控三菱CNC的硬件连接检查与设置执行完毕向系统送电后&#xff0c;显示器上的READY绿灯仍然不亮。而且在〔诊断〕――〔报警〕 画面上显示很多报警内容&#xff0c;哪些是开机时必须设置的呢&#xff1f;又如何解除故障报警呢&#xff1f;1.开机参数1.1 基本参数的设置原装系统…

计算机如何更新苹果系统,苹果系统怎么更新_苹果电脑mac如何更新升级系统-win7之家...

苹果电脑跟windows系统一样&#xff0c;也是会在发布之后不断的推送新版本让用户们进行升级&#xff0c;不仅可以修复bug还可以增加新功能&#xff0c;不过很多用户可能都会有一个疑问&#xff0c;就是苹果系统怎么更新呢&#xff1f;方法并不难&#xff0c;本文给大家讲述一下…

手术步骤_近视飞秒激光手术和传统Lasik手术比较

传统LasikLASIK手术操作时分为两个步骤&#xff1a;第一个步骤医生需要制作一个角膜瓣&#xff1b;第二个步骤是掀开角膜瓣&#xff0c;以准分子激光雕琢角膜&#xff0c;进行视力矫正&#xff0c;雕琢完毕后将角膜瓣复位即手术完成。传统的角膜制瓣是用机械式的设备与一个微型…