深入理解 Java HelloWorld

Java 的 Hello World 代码

public class HelloWorld {

    /**
     *
     * @param args
     */

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println("Hello World");
    }

}

编译运行

$ javac HelloWorld.java
$ java HelloWorld
Hello World

功能就是在控制台打印 Hello World 字符串, 我们这里深入每一个步骤,探讨是如何将字符串打印到控制台的。

环境

我们刚才的程序运行在 Ubuntu Linux 的控制台 bash 程序里。 javac 是编译器, java 运行虚拟机,载入 HelloWorld.class 执行 HelloWorld 类的 main 函数,这部分是属于虚拟机的内容,暂时不做考虑,我们主要从代码调用的步骤分析。

System 类

从代码逻辑上,我们很容易看出是 System 类的 out 成员 println 函数执行了打印操作:

public final class System {

    /**
     * Default input stream.
     */
    public static final InputStream in;

    /**
     * Default output stream.
     */
    public static final PrintStream out;

    /**
     * Default error output stream.
     */
    public static final PrintStream err;

    private static final String lineSeparator;
    private static Properties systemProperties;

    static {
        err = new PrintStream(new FileOutputStream(FileDescriptor.err));
        out = new PrintStream(new FileOutputStream(FileDescriptor.out));
        in = new BufferedInputStream(new FileInputStream(FileDescriptor.in));
        lineSeparator = System.getProperty("line.separator");
    }

out 是个 PrintStream

PrintStream 类

    /**
     * Prints a string followed by a newline. The string is converted to an array of bytes using
     * the encoding chosen during the construction of this stream. The bytes are
     * then written to the target stream with {@code write(int)}.
     *
     * <p>If an I/O error occurs, this stream's error state is set to {@code true}.
     *
     * @param str
     *            the string to print to the target stream.
     * @see #write(int)
     */
    public synchronized void println(String str) {
        print(str);
        newline();
    }

具体的工作交给了 print ,  我们在这个类里面可以看到 newline 只是打印了两个特殊字符,换行。

    public synchronized void print(String str) {
        if (out == null) {
            setError();
            return;
        }
        if (str == null) {
            print("null");
            return;
        }

        try {
            if (encoding == null) {
                write(str.getBytes());
            } else {
                write(str.getBytes(encoding));
            }
        } catch (IOException e) {
            setError();
        }
    }

进一步的工作由 write 函数完成:

    public synchronized void write(int oneByte) {
        if (out == null) {
            setError();
            return;
        }
        try {
            out.write(oneByte);
            int b = oneByte & 0xFF;
            // 0x0A is ASCII newline, 0x15 is EBCDIC newline.
            boolean isNewline = b == 0x0A || b == 0x15;
            if (autoFlush && isNewline) {
                flush();
            }
        } catch (IOException e) {
            setError();
        }
    }

又来了个 out 这个,out 是 来自 OutputStream 的实现类 public class FileOutputStream extends OutputStream

public class FileOutputStream extends OutputStream {

    private FileDescriptor fd;
    private final boolean shouldClose;

    /** The unique file channel. Lazily initialized because it's rarely needed. */
    private FileChannel channel;

    /** File access mode */
    private final int mode;

    private final CloseGuard guard = CloseGuard.get();

FileDescriptor

public final class FileDescriptor {

    /**
     * Corresponds to {@code stdin}.
     */
    public static final FileDescriptor in = new FileDescriptor();

    /**
     * Corresponds to {@code stdout}.
     */
    public static final FileDescriptor out = new FileDescriptor();

    /**
     * Corresponds to {@code stderr}.
     */
    public static final FileDescriptor err = new FileDescriptor();

    /**
     * The Unix file descriptor backing this FileDescriptor.
     * A value of -1 indicates that this FileDescriptor is invalid.
     */
    private int descriptor = -1;

    static {
        in.descriptor = STDIN_FILENO;
        out.descriptor = STDOUT_FILENO;
        err.descriptor = STDERR_FILENO;
    }

这里来到 STDOUT_FILENO, 该变量定义在: 在<stdio.h>。

STDIN_FILENO等是文件描述符,是非负整数,一般定义为0, 1, 2,属于没有buffer的I/O,直接调用系统调用,在<unistd.h>。

参考i: http://blog.csdn.net/xiaoxi2xin/article/details/5524769

    @Override
    public void write(byte[] buffer, int byteOffset, int byteCount) throws IOException {
        IoBridge.write(fd, buffer, byteOffset, byteCount);
    }

    @Override
    public void write(int oneByte) throws IOException {
        write(new 

最后是调用 os 的 write

深入理解 Java HelloWorld

时间: 2024-08-24 13:51:36

深入理解 Java HelloWorld的相关文章

【深入理解Java虚拟机】类加载机制

本文内容来源于<深入理解Java虚拟机>一书,非常推荐大家去看一下这本书. 本系列其他文章: [深入理解Java虚拟机]Java内存区域模型.对象创建过程.常见OOM [深入理解Java虚拟机]垃圾回收机制 1.类加载机制概述 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 在java中,类型的加载.连接和初始化过程都是在程序运行期间完成的,这种策略虽然会带来一些性能开销,但是却为jav

深入理解Java虚拟机到底是什么

摘自:http://blog.csdn.net/zhangjg_blog/article/details/20380971 什么是Java虚拟机 我们都知道Java程序必须在虚拟机上运行.那么虚拟机到底是什么呢?先看网上搜索到的比较靠谱的解释: 虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的.Java虚拟机有自己完善的硬体架构,如处理器.堆栈.寄存器等,还具有相应的指令系统.JVM屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的

java笔记--理解java类加载器以及ClassLoader类

类加载器概述: java类的加载是由虚拟机来完成的,虚拟机把描述类的Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成能被java虚拟机直接使用的java类型,这就是虚拟机的类加载机制.JVM中用来完成上述功能的具体实现就是类加载器.类加载器读取.class字节码文件将其转换成java.lang.Class类的一个实例.每个实例用来表示一个java类.通过该实例的newInstance()方法可以创建出一个该类的对象. 类的生命周期: 类从加载到虚拟机内存到被从内存中释放,经历的

(1) 深入理解Java虚拟机到底是什么?

好文转载:http://blog.csdn.net/zhangjg_blog/article/details/20380971 什么是Java虚拟机 作为一个Java程序员,我们每天都在写Java代码,我们写的代码都是在一个叫做Java虚拟机的东西上执行的.但是如果要问什么是虚拟机,恐怕很多人就会模棱两可了.在本文中,我会写下我对虚拟机的理解.因为能力所限,可能有些地方描述的不够欠当.如果你有不同的理解,欢迎交流. 我们都知道Java程序必须在虚拟机上运行.那么虚拟机到底是什么呢?先看网上搜索到

读深入理解Java中的String(包括JVM)一文总结和提升

读深入理解Java中的String(包括JVM)一文总结和提升 摘要:String作为Java语言中的字符串模拟类,无论是实际的编程工作还是笔试面试过程,都需要我们都String类非常熟悉,对于String类的大部分字符串操作方法,都必须达到熟练运用的程度才行.但是,笔试和面试过程中,面试官往往喜欢问一些String特性相关的题目,来考察面试者对于String基础知识的掌握是否牢固.(本人尚未研读深入理解JVM这本书,分析JVM都是查看网上资料来分析的,若在接下来的内容有分析不到位的地方请见谅和

《深入理解Java集合框架》系列文章

Introduction 关于C++标准模板库(Standard Template Library, STL)的书籍和资料有很多,关于Java集合框架(Java Collections Framework, JCF)的资料却很少,甚至很难找到一本专门介绍它的书籍,这给Java学习者们带来不小的麻烦.我深深的不解其中的原因.虽然JCF设计参考了STL,但其定位不是Java版的STL,而是要实现一个精简紧凑的容器框架,对STL的介绍自然不能替代对JCF的介绍. 本系列文章主要从数据结构和算法层面分析

深入理解Java:注解(Annotation)--注解处理器

深入理解Java:注解(Annotation)--注解处理器 如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了.使用注解的过程中,很重要的一部分就是创建于使用注解处理器.Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处理器. 注解处理器类库(java.lang.reflect.AnnotatedElement): Java使用Annotation接口来代表程序元素前面的注解,该接口是所有Annotation类型的父接口.除此之外,Java在java.l

深入理解Java:注解(Annotation)自己定义注解入门

深入理解Java:注解(Annotation)自己定义注解入门 要深入学习注解.我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前.我们就必须要了解Java为我们提供的元注解和相关定义注解的语法. 元注解: 元注解的作用就是负责注解其它注解. Java5.0定义了4个标准的meta-annotation类型.它们被用来提供对其它 annotation类型作说明.Java5.0定义的元注解: [email protected], [email protected], [email pro

深入理解Java PriorityQueue

深入理解Java PriorityQueue PriorityQueue 本文github地址 Java中PriorityQueue通过二叉小顶堆实现,可以用一棵完全二叉树表示.本文从Queue接口函数出发,结合生动的图解,深入浅出地分析PriorityQueue每个操作的具体过程和时间复杂度,将让读者建立对PriorityQueue建立清晰而深入的认识. 总体介绍 前面以Java ArrayDeque为例讲解了Stack和Queue,其实还有一种特殊的队列叫做PriorityQueue,即优先