`

深入理解Java HelloWorld

    博客分类:
  • java
阅读更多

HelloWorld是每个Java程序员都知道的程序。它很简单,但是简单的开始可以引导你去深入了解更复杂的东西。这篇文章将探究从这个HelloWorld这个简单程序中可以学到的东西。如果你对HelloWorld有独到的理解,欢迎留下你的评论。

HelloWorld.java

1
2
3
4
5
6
7
8
9
10
11
12
13
public class HelloWorld {
 
    /**
     *
     * @param args
     */
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println("Hello World");
    }
 
}

1、为什么一切都是从类开始?

Java程序是从类开始构建的, 每个方法和字段都必须在类里面。这是由于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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Compiled from "HelloWorld.java"
public class HelloWorld extends java.lang.Object{
public HelloWorld();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return
  
public static void main(java.lang.String[]);
  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;)V
   8:   return
}

上面的代码包含两个方法: 一个是编译器推断出来的默认的构造器;另外一个是main方法。

接下来,每个方法都有一系列的指令。比如aload_0、invokespecial #1等等。可以在Java字节码指令集中查到每个指令的功能,例如aload_0用来从局部变量0中加载一个引用到堆栈,getstatic用来获取类的一个静态字段值。可以注意到,getstatic指令之后的“#2″指向的是运行期常量池。常量池是JVM运行时数据区之一。我们可以通过“javap -verbose”命令来查看常量池。

另外, 每个指令从一个数字开始,比如0、1、4等等。在.class文件中,每个方法都有一个对应的字节码数组。这些数字对应于存储每个操作码及其参数的数组的下标。每个操作码都是1个字节长度,并且指令可以有0个或多个参数。这就是为什么这些数字不是连续的原因。

现在,我们使用“javap -verbose”这个命令来进一步观察这个类。

1
javap -classpath . -verbose HelloWorld
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
Compiled from "HelloWorld.java"
public class HelloWorld extends java.lang.Object
  SourceFile: "HelloWorld.java"
  minor version: 0
  major version: 50
  Constant pool:
const #1 = Method   #6.#15; //  java/lang/Object."<init>":()V
const #2 = Field    #16.#17;    //  java/lang/System.out:Ljava/io/PrintStream;
const #3 = String   #18;    //  Hello World
const #4 = Method   #19.#20;    //  java/io/PrintStream.println:(Ljava/lang/String;)V
const #5 = class    #21;    //  HelloWorld
const #6 = class    #22;    //  java/lang/Object
const #7 = Asciz    <init>;
const #8 = Asciz    ()V;
const #9 = Asciz    Code;
const #10 = Asciz   LineNumberTable;
const #11 = Asciz   main;
const #12 = Asciz   ([Ljava/lang/String;)V;
const #13 = Asciz   SourceFile;
const #14 = Asciz   HelloWorld.java;
const #15 = NameAndType #7:#8;//  "<init>":()V
const #16 = class   #23;    //  java/lang/System
const #17 = NameAndType #24:#25;//  out:Ljava/io/PrintStream;
const #18 = Asciz   Hello World;
const #19 = class   #26;    //  java/io/PrintStream
const #20 = NameAndType #27:#28;//  println:(Ljava/lang/String;)V
const #21 = Asciz   HelloWorld;
const #22 = Asciz   java/lang/Object;
const #23 = Asciz   java/lang/System;
const #24 = Asciz   out;
const #25 = Asciz   Ljava/io/PrintStream;;
const #26 = Asciz   java/io/PrintStream;
const #27 = Asciz   println;
const #28 = Asciz   (Ljava/lang/String;)V;
  
{
public HelloWorld();
  Code:
   Stack=1, Locals=1, Args_size=1
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return
  LineNumberTable:
   line 2: 0
  
  
public static void main(java.lang.String[]);
  Code:
   Stack=2, Locals=1, Args_size=1
   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;)V
   8:   return
  LineNumberTable:
   line 9: 0
   line 10: 8
}

引用JVM规范中的描述:运行期常量池提供的功能类似传统编程语言的符号表所起作用, 尽管它比传统的符号表包含的内容更广范。

“invokespecial #1″指令中的“#1″指向常量池中的#1常量。这个常量是 “Method #6.#15;”。通过这个数字,我们可以递归地得到最终的常量。

LineNumberTable为调试器提供了用来指示Java源代码与字节码指令之间的对应信息。例如,Java源代码中的第9行对应于main方法中的字节码0,并且第10行对应于字节码8。

如果想要了解更多关于字节码的内容,可以创建一个更加复杂的类进行编译和查看,HelloWorld真的只是一个开始。

4、HelloWorld在JVM中是如何执行的?

现在的问题是JVM是怎样加载这个类并调用main方法?

在main方法执行之前, JVM需要加载链接以及初始化这个类。
1. 加载将类/接口的二进制形式装入JVM中。
2. 链接将二进制类型的数据融入到JVM的运行时。链接由3个步骤组成:验证、准备、以及解析(可选)。验证确保类、接口在结构上是正确的;准备涉及到为类、接口分配所需要的内存;解析是解析符号引用。
3. 最后,初始化为类变量分配正确的初始值。

加载工作是由Java类加载器来完成的。当JVM启动时,会使用下面三个类加载器:

  1. Bootstrap类加载器:加载位于/jre/lib目录下的核心Java类库。它是JVM核心的一部分,并且使用本地代码编写。
  2. 扩展类加载器:加载扩展目录中的代码(比如/jar/lib/ext)。
  3. 系统类加载器:加载在CLASSPATH上的代码。

所以,HelloWorld类是由系统加载器加载的。当main方法执行时,它会触发加载其它依赖的类,进行链接和初始化。前提是它们已经存在。

最后,main()帧被压入JVM堆栈,并且程序计数器(PC)也进行了相应的设置。然后,PC指示将println()帧压入JVM堆栈栈顶。当main()方法执行完毕会被弹出堆栈,至此执行过程就结束了。

参考文档

  1. 加载
  2. 类加载机制
  3. 类加载器
分享到:
评论

相关推荐

    Mac下实现Java HelloWorld

    "Mac下实现Java HelloWorld"这个话题主要涵盖了如何在Mac系统中配置Java环境并执行第一个Java程序。以下是对这个过程的详细阐述: 首先,确保你的Mac已经安装了Java开发工具(JDK)。可以通过在终端输入`javac -...

    理解java的helloworld.pdf

    在本文中,我们将深入理解Java HelloWorld程序背后的原理,以及如何解决新手在尝试编写和运行第一个Java程序时可能遇到的问题。 首先,让我们看一个基本的Java HelloWorld程序: ```java public class HelloWorld ...

    Java ME Hello World

    **Java ME Hello World** Java ME(Micro Edition)是Java平台的一个子集,主要用于移动设备、嵌入式...通过这个简单的实例,开发者可以开始了解Java ME平台的工作原理,进而深入学习如何开发更复杂的移动应用程序。

    java hello world

    然后,通过Java虚拟机(JVM)运行编译后的字节码文件,命令为`java HelloWorld`(假设类名与文件名相同,且不包含扩展名)。 Java作为一种强类型、面向对象的语言,有着丰富的库支持和跨平台的特性。它的语法严谨,...

    Java JNI HelloWorld.rar

    在这个"Java JNI HelloWorld"示例中,我们将深入探讨如何使用JNI来创建一个简单的“Hello, World!”程序。 首先,`HelloWorld.java`是Java源代码文件,其中定义了一个本地方法`native void sayHello()`。在Java中,...

    Hello world

    例如,如果类名为`HelloWorld`,则文件名为`HelloWorld.java`。Java是严格的面向对象语言,因此每个源代码文件至少包含一个公共类(public class)。 3. **公共类(Public Class)**:在Java中,`public`关键字表示...

    Java动态代理helloworld

    本篇文章将深入探讨Java动态代理的概念、原理以及如何通过一个简单的"Hello, World!"示例来理解它。 动态代理,顾名思义,是在程序运行时动态地生成代理对象。与静态代理(编译时已知)相比,动态代理更加灵活,...

    Java | hello world文本编译代码

    "的源代码,非常适合那些希望快速了解Java编程基础的新手。 在Java中,"Hello, World!"程序通常用一个简单的类和主方法来编写。下面,我们将详细解释这个过程: 1. **创建Java源文件**: Java源代码以`.java`为...

    Java Helloworld 程序.rar

    3. **编写代码**:打开文本编辑器,如Notepad++或Visual Studio Code,创建一个新的文件,命名为`HelloWorld.java`。在文件中输入以下代码: ```java public class HelloWorld { public static void main(String...

    理解java的helloworld.doc

    本文将深入解析 HelloWorld 示例背后的原理和常见问题,帮助读者更好地理解和掌握 Java 开发的基础。 首先,我们需要确保已经正确安装了 JDK(Java Development Kit)。JDK 提供了编译和运行 Java 程序所需的所有...

    Helloworld_helloworld_

    在提供的描述中,“输出HELLOWORLD然后输出Helloworld最后的最后的输出Helloworld”暗示了可能的练习目标是让初学者了解字符串的处理和输出格式。这可能涉及到变量的使用、字符串的拼接以及大小写的转换。例如,可以...

    理解java的helloworld[归类].pdf

    Java的 HelloWorld 示例是每个初学者接触编程语言时的必经之路。这个简单的程序不仅标志着学习的开始,也是理解和掌握Java语法、编译及运行过程的基础。在这个过程中,我们经常会遇到一些初学者常犯的错误,这些错误...

    Java入门HELLOWORLD

    在这个教程中,我们将深入探讨Java的基本概念和 HelloWorld 示例,帮助初学者建立起对Java编程的基础理解。 首先,让我们了解Java的起源。Java是由Sun Microsystems(后被Oracle收购)的詹姆斯·高斯林(James ...

    rabbitmq HelloWorld java 代码

    本教程将深入讲解如何使用Java进行RabbitMQ的HelloWorld程序编写。 首先,我们需要了解RabbitMQ的基本概念。RabbitMQ是一个开源的消息代理,它作为生产者和消费者之间的中间人,接收、存储并转发消息。生产者是发送...

    实现java_HelloWorld小程序.pdf

    ### Java HelloWorld 小程序实现详解 #### 一、概述 Java HelloWorld 程序作为学习 Java 编程语言的第一步,具有重要的意义。它不仅帮助初学者熟悉 Java 的基本语法结构,还能够让大家掌握如何搭建 Java 开发环境...

    关于java内存的小常识,以helloworld程序为例

    本文将以经典的"HelloWorld"程序为例,深入浅出地讲解Java内存的几个关键区域。 首先,Java程序在运行时,其内存主要分为以下几个部分: 1. **栈(Stack)**:栈主要用于存储基本类型变量(如int、float等)和对象...

    Spring4 HelloWorld

    Spring框架是Java开发中广泛使用的轻量级框架,它以其依赖...学习和理解"Spring4 HelloWorld",不仅能够帮助初学者掌握Spring的基本用法,也为进一步深入学习Spring的其他高级特性,如AOP、MVC、JPA等打下坚实基础。

    Java调用C程序之HelloWorld

    本主题“Java调用C程序之HelloWorld”将深入探讨如何在Java程序中调用C语言编写的代码,实现二者的交互。这个过程通常通过Java的JNI(Java Native Interface)技术来完成。 首先,我们需要了解JNI的概念。JNI是Java...

    Axis开发WebService Helloworld实例

    1. 创建一个新的Java类,命名为`HelloWorld.java`,包含一个公共方法,例如: ```java public class HelloWorld { public String sayHello(String name) { return "Hello, " + name + "!"; } } ``` 2. 使用...

    Android HelloWorld程序

    接下来,我们将深入探讨Android HelloWorld程序的相关知识点。 首先,Android是Google主导的开源移动操作系统,主要应用于智能手机和平板电脑,但其生态系统也涵盖了电视、汽车、穿戴设备等多种智能硬件。Android...

Global site tag (gtag.js) - Google Analytics