当前位置:首页 > 专题范文 > 公文范文 >

我们能从javaHelloWorld学到什么(完整文档)

时间:2022-07-30 11:50:01 来源:网友投稿

下面是小编为大家整理的我们能从javaHelloWorld学到什么(完整文档),供大家参考。

我们能从javaHelloWorld学到什么(完整文档)

 

 我们能从 java 的 HelloWorld 学到什么?

  •

 #文章 •

 java •

 GB 原创及翻译小组 评论(0)阅读(511) 申请达人, 去除赞助商链接 这是每个 Java 程序员都知道的。

 虽然简单, 但是从一个简单的问题可以引入更深的思考。在这篇文章中, 我们将讨论这个简单的程序。

 如果能更多的帮到你, 请留下宝贵的意见。

 HelloWorld.java 1. public class HelloWorld { 2.

 /** 3.

  * @param args 4.

  */ 5.

 public static void main(String[] args) {

 6.

  // TODO Auto-generated method stub 7.

  System.out.println("Hello World"); 8.

 } 9. }

 1、 为什么一切都开始于一个类?

 Java 程序是由类组成, 一个类包含方法和属性。

 这是由于它的面向对象的特征:

 一切皆对象, 每个对象都是一个类的实例。

 面向对象编程有很多优势, 比如更好的模块化, 扩展性强等 2、 为什么总有一个“main”方法?

 “main”方法是程序的入口, 它是静态的。

 “static”是指该方法是类的一部分, 而不是对象的一部分。

 这是为什么? 我们为什么不把一个非静态方法作为程序的入口?

 如果方法不是静态的, 那么需要创建一个对象后才能使用方法。因为必须用对象去调用方法。对于程序的入口, 这是不现实的。

 所以, 程序的入口方法是静态的。

 参数“String[] args”表示一个字符串数组可以被传入到该程序, 用来初始化程序。

 3、 HelloWorld 的字节码 执行这个程序, Java 文件首先编译为 java 字节码储存在.class 文件里。

 字节码是什么样子的呢?

 首先, 字节码本身是无法读取。

 如果我们用一个十六进制编辑器打开, 它看起来像下面这样:

  我们能看到很多操作码(比如

 CA、 4C 等)

 在字节码上, 它们每个都有一个相应的助记码(比如, aload_0 在下面的例子中)。操作码是不可读的, 但我们可以用 javap 命令查看.class文件的助记符形式。

 “javap -C”打印出每个方法的反汇编代码。

 反汇编代码的意思是包括 Java 字节码的说明。

 1. javap -classpath .

 -c HelloWorld

  1. Compiled from "HelloWorld.java" 2. public class HelloWorld extends java.lang.Object{ 3. public HelloWorld(); 4.

  Code: 5.

 0: aload_0 6.

 1: invokespecial #1; //Method java/lang/Object."<init>":()V 7.

 4: return 8.

  9. public static void main(java.lang.String[]); 10.

  Code: 11.

 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 12.

 3: ldc #3; //String Hello World

 13.

 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 14.

 8: return 15. }

 上面的代码中包含两个方法:

 一个是默认构造函数, 这是由编译器推断出, 另一个是 main方法。

 每个方法下面, 都有一系列指令, 比如 aload_0,invokespecial #1,等 下面的每个方法, 也有说明, 如 aload_0, invokespecial# 1, 等指令可以在 java 指令清单里查到。

 例如, aload_0 指令是加载一个从栈中引用的本地变量 0, getstatic 指令获取一个类的静态字段值。

 注意“#2” 指令在 getstatic 指令后指向运行常量池。

 www.zglengcc.com常量池是一个 JVM 运行时数据区, 查看 。

 我们可以用“javap -verbose”命令来查看常量池。

 此外, 每个指令开始于一个数字, 如 0,1, 4 等。

 在.class 文件中, 每个方法都有一个对应的字节码数组。

 这些数字对应的每一个操作码和它的参数都存储在数组中的索引中。

 每个操作码为 1 个字节, 指令可以有 0 个或多个参数。

 这就是为什么数字是不连续的。

 现在, 我们可以用“javap -verbose” 查看.class 文件进一步研究。

 1. javap -classpath . -verbose HelloWorld

  1. Compiled from "HelloWorld.java" 2. public class HelloWorld extends java.lang.Object 3.

  SourceFile: "HelloWorld.java" 4.

  minor version: 0 5.

  major version: 50 6.

  Constant pool: 7. const #1 = Method #6.#15; //

 java/lang/Object."<init>":()V 8. const #2 = Field #16.#17; //

 java/lang/System.out:Ljava/io/PrintStream; 9. const #3 = String #18; //

 Hello World

 10. const #4 = Method #19.#20; //

 java/io/PrintStream.println:(Ljava/lang/String;)V 11. const #5 = class #21; //

 HelloWorld 12. const #6 = class #22; //

 java/lang/Object 13. const #7 = Asciz <init>; 14. const #8 = Asciz ()V; 15. const #9 = Asciz Code; 16. const #10 = Asciz LineNumberTable; 17. const #11 = Asciz main; 18. const #12 = Asciz ([Ljava/lang/String;)V; 19. const #13 = Asciz SourceFile; 20. const #14 = Asciz HelloWorld.java; 21. const #15 = NameAndType #7:#8;//

 "<init>":()V 22. const #16 = class #23; //

 java/lang/System 23. const #17 = NameAndType #24:#25;//

 out:Ljava/io/PrintStream; 24. const #18 = Asciz Hello World; 25. const #19 = class #26; //

 java/io/PrintStream 26. const #20 = NameAndType #27:#28;//

 println:(Ljava/lang/String;)V 27. const #21 = Asciz HelloWorld; 28. const #22 = Asciz java/lang/Object; 29. const #23 = Asciz java/lang/System; 30. const #24 = Asciz out; 31. const #25 = Asciz Ljava/io/PrintStream;; 32. const #26 = Asciz java/io/PrintStream; 33. const #27 = Asciz println; 34. const #28 = Asciz (Ljava/lang/String;)V; 35.

  36. { 37. public HelloWorld(); 38.

  Code: 39.

 Stack=1, Locals=1, Args_size=1

 40.

 0: aload_0 41.

 1: invokespecial #1; //Method java/lang/Object."<init>":()V 42.

 4: return 43.

  LineNumberTable:

 44.

 line 2: 0 45.

  46.

  47. public static void main(java.lang.String[]); 48.

  Code: 49.

 Stack=2, Locals=1, Args_size=1 50.

 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 51.

 3: ldc #3; //String Hello World 52.

 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 53.

 8: return 54.

  LineNumberTable:

 55.

 line 9: 0 56.

 line 10: 8 57. }

 JVM 定义:

 运行常量池提供一个类似于传统的编程语言的符号表函数, 尽管它包含了比典型的符号表范围更广的数据 “invokespecial #1″指令指向#1 常量在常量池中.常量是”Method #6.#15;“从数字上看, 我们就可以按递归方式来得到最终的常量。

 LineNumberTable 提供用来调试 java 源代码对应字节码的行数信息例如, 在 main 方法里Java 源代码第 9 行对应字节码 0, 第 10 行对应字节码 8。

 如果你想知道更多关于字节码, 您可以创建和编译一个更复杂的类来看一看。

 HelloWorld确实是个很简单的例子。

 4、 它是如何在 JVM 中执行?

 现在的问题是如何 JVM 加载类并调用 main 方法?

 在 main 方法执行之前, JVM 需要分三步走加载、 连接以及初始化该类。

 1)

 加载二进制的类和接口到 jvm 中。

 2)

 连接合并二进制数据到正在运行状态的 jvm。

 连接有三步构成, 验证、 准备、 解析。

 验证确保了类/接口在结构上正确的;准备工作包括所需要的类/接口分配内存;解析符号引用。

 最后 3)

 初始化变量并初始化值

 这个装载工作是由 Java 类加载器完成的。

 当 JVM 启动时, 3 个类加载器被使用:

 1.引导类加载器:

 加载位于/ jre / lib 目录的核心 Java 库。

 这是 jvm 核心的一部分, 并且是原生的代码。

 2.扩展类加载器:

 加载代码的扩展目录(例如, /jar/ lib / ext 目录)

 。

 3.系统类加载器:

 在 CLASSPATH 中找到负载代码。

 所以 HelloWorld 类是由系统类加载器加载。

 当执行的主要方法, 它会触发加载, 链接和其他相关的类的初始化(查看)

 , 如果它们存在。

 最后, main()的帧被加载到 jvm 堆栈,程序计数器(PC)

 被相应地设置。

 程序计数器然后指示 println()帧的加载到 JVM 堆栈。

 当 main()

 方法完成后, 它会从堆栈中弹出执行完成。

推荐访问:我们能从javaHelloWorld学到什么 学到 完整 文档