java helloworld源代码_java Hello world 源码执行流程详解

java helloworld源代码_java Hello world 源码执行流程详解helloworld作为我们学习的第一个个程序,看起来很简单,但是要理解其执行的具体流程还是需要很深的功底,包括对组成原理,操作系统的理解,今天将javahelloworld进行整理一下吧!!废话不多说,先上helloworldpublicclassMain{publicstaticvoidmain(String[]args){Strings=”helloWorl…

大家好,又见面了,我是你们的朋友全栈君。

hello world 作为我们学习的第一个个程序,看起来很简单,但是要理解其执行的具体流程还是需要很深的功底,包括对组成原理,操作系统的理解,今天将java hello world 进行整理一下吧!!

废话不多说,先上hello world

public class Main {

public static void main(String[] args) {

String s = “helloWorld”;

String s2 = new String(“helloWorld”);

System.out.println(s);

System.out.println(s2);

}

}

很简单的程序,具体执行是怎么样的?

相信大家都知道 java 代码的可移植性,是由于java解释器和虚拟机,所以处理java原代码的过程,就是java代码执行的过程:

Java 代码的运行过程?

Java 源代码 -> 编辑器 -> 字节码文件

字节码 -> JVM -> 机器码文件

每一种平台的解释器是不同的,但是实现的虚拟机是相同的,这也就是 Java 为什么能够 跨平台的原因

java 原文件通过编译器编译成.class字节码文件,字节码文件通过 JVM 虚拟机,生成机器码文件

1. 代码编译 ,词法语法语义分析,将java 原代码编译成字节码文件;

我们的.java 文件最终会转换为.class文件

2. 类加载机制,采用双亲委派避免重复加载(类名+类加载器),加载,验证,准备(准备会对一些常量进行初始化,遍历初始化为0或null),解析,初始化

我们知道 JVM 虚拟机的入口就是类加载器,在加载java中的类时采用双亲委托机制,可以防止用户新写的类,替代jre中的类。

当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父 类去完 成,每一个层次类加载器都是如此,因此所有的加载请求都应该传送到启动类加载其中, 只有当父类 加载器反馈自己无法完成这个请求的时候(在它的加载路径下没有找到所需加载的 Class), 子类加 载器才会尝试自己去加载。

类加载器有,启动(Bootstrap)类加载器,扩展(Extension)类加载器,系统(System)类加载器,自定义类加载器

我们的Main类由系统类加载器进行加载,委托给父类加载器

在JVM中表示两个class对象是否为同一个类对象存在两个必要条件

类的完整类名必须一致,包括包名。

加载这个类的ClassLoader(指ClassLoader实例对象)必须相同

8753649b6be2?utm_campaign=haruki

hw.PNG

详细的类加载过程是:

JVM 类加载机制分为五个部分:加载,验证,准备,解析,初始化。

加载, 这个阶段会在内存中生成一个代表这个类的 java.lang.Class 作为方法区这个类的各种数 据的入口。

验证,确保 Class文件的字节流中包含的信息是否符合当前虚拟机的要求

准备,是正式为类变量分配内存并设置类变量的初始值阶段,public static int v = 8080,实际 上变量 v 在准备阶段过后的初始值为 0 而不是 8080,但是如果声明的是常量就是8080,例如 public static final int v = 8080。

4.解析,解析阶段是指虚拟机将常量池中的符号引用替换为直接引用的过程。

3. 在jvm内存中栈和本地线程栈是线程私有的,会在线程中创建一个main方法的栈帧

在main方法栈帧中,里面S,S2存放在其中的字符变量表中,然后“helloword”是一个字符串常量,在jvm中会存放在方法区中的字符常量池中的,然后将其从常量池中弹到操作数栈空间,然后赋值到s的空间中。这个 new String(“helloword”), 先指向堆空间,堆空间再去指向 方法区常量池中。复制一份常量数据再放到s2 对应的寄存器空间中。然后字面变量在字符变量表中指向这些空间。

具体可以使用 javap -c Main.class 解析.class 文件

Compiled from “Main.java”

public class com.bupt.learn.Main {

public com.bupt.learn.Main();

Code:

0: aload_0

1: invokespecial #1 // Method java/lang/Object.””:()V

4: return

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

Code:

// 将 helloword 从常量池推送到栈顶

0: ldc #2 // String helloWorld

// 将栈顶 引用 型数值存入第二个局部变量

2: astore_1

// 堆中创建一个对象,并将其引用值压入栈顶

3: new #3 // class java/lang/String

// 复制栈顶数值并将复制值压入栈顶

6: dup

// 将 helloword 从常量池推送到栈顶

7: ldc #2 // String helloWorld

// 调用超类构造方法,实例初始化方法,私有方法

9: invokespecial #4 // Method java/lang/String.””:(Ljava/lang/String;)V

// 将栈顶 引用 型数值存入第三个局部变量

12: astore_2

// 获取指定类的静态字段,并将其压入栈顶

13: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;

// 将第二个 引用 型局部变量推送至栈顶

16: aload_1

// 调用实例方法

17: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V

20: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;

23: aload_2

24: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V

27: return

}

8753649b6be2?utm_campaign=haruki

jvm.PNG

4. System.out.println(s):系统加载System.class字节码文件到方法区,并且系统会默认在堆区创建System.out、System.in、System.err三个对象。

字符串在被输出时会自动调用toString()方法。

println 是 java 原始的IO包,是使用 BIO 进行输出

一次I/O的完成的步骤

当进程发起系统调用时,这个系统调用就进入内核模式,然后开始I/O操作

I/O操作分为两个步骤;

1、磁盘把数据装载到内核的内存空间,

2、内核的内存空间的数据copy到用户的内存空间中(此过程是I/O发生的地方)

阻塞:进程发起I/O调用,进程又不得不等待I/O的完成,此时CPU把进程切换出去,进程处于睡眠状态则此过程为阻塞I/O

阻塞I/O系统怎么通知进程?

I/O完成,系统直接通知进程,则进程被唤醒

8753649b6be2?utm_campaign=haruki

BIO.PNG

5. JVM 字节码执行引擎 生成机器节码文件,执行系统找到Main方法为其分配cpu进行执行;

6. cpu的执行分为取值,译码,执行 操作系统开始执行指令失败,缺中断发送; 操作系统分配一页内存,将代码从磁盘读入,继续执行

7. 程序执行系统调用,在文件描述符中写一字符串

8. 操作系统检查字符串的位置是否正确,操作系统找到字符串被送往的设备

9. 设备是一个伪终端,又一个进程控制,操作系统将字符串送给该进程,该进程告诉窗口系统它要显示字符串

10. 窗口系统确定这是一个合法的操作,然后将字符串转成像素

11. 视频硬件将成像素表示转换成一组模拟信号控制显示器在(重画屏幕)

12 . 显示器发射电子束,你在屏幕上看到“hello world”

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/140367.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • java8获取以秒单位的时间戳

    java8获取以秒单位的时间戳importjava.sql.Timestamp;//不带小时,分钟publicstaticlonggetTimeStamp(intlen){              //LocalTime.of(0,0)换成LocalTime.now()可获得完整的时间戳(13位毫秒)longtimestamp=Timestamp.valueOf(LocalDateTim…

    2022年9月6日
    7
  • 命令模式 Command「建议收藏」

    命令模式 Command「建议收藏」命令模式 Command动机模式定义实例结构要点总结笔记动机在软件构建过程中,“行为请求者”与”行为实现者”通常呈现一种”紧耦合”,但在某些场合—-比如需要对行为进行记录,撤销/重(Undo / Redo),事务”等处理,这种无法抵御变化的紧耦合是不合适的在这种情况下,如何将”行为请求者”和”行为实现这”解耦?将一组行为抽象为对象,可以实现两者之间的松耦合模式定义将一个请求(行为)封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作实例#i

    2022年8月8日
    6
  • textview可复制_长按复制是怎么做的

    textview可复制_长按复制是怎么做的前段时间因为项目需求实现TextView长按复制的功能,特意上百度差了一下有不少实现这个功能的方法,隔了好久也怕忘了,总结一下:先推荐目前感觉最好用的方法:在布局文件的TextView控件属性中增加一句话:android:textIsSelectable="true",不过这个方法需要只有androidsdk11起才支持,v11以下则不行了。不过现在的版本这个应该也不成问题了xml文件中可以设…

    2022年9月29日
    2
  • k8s(二)搭建「建议收藏」

    k8s(二)搭建「建议收藏」k8s安装 初始化环境kubernetes必要组件安装集群安装一主多从多主多从安装 初始化环境minibuke 用于快速构建单节点k8s的工具kubeadm 用于快速搭建k8s集群的工具二进制包 从官网下载每个组件的二进制包 一次去安装 对于理解k8s更有效作用nathostmaster10.0.3.11192.168.56.101node110.0.3.12192.168.56.102node210.0.3.14192.168.56.1

    2022年8月9日
    7
  • 宽字节注入原理学习

    宽字节注入原理学习0x01开篇本题用到考点是宽字节注入,遇到这种注入类型学习记录。推荐两篇链接:浅析白盒审计中的字符编码及SQL注入|离别歌Von的博客|VonBlog为方便自我下次忘记,总结一下:1.宽字节涉及到编码问题,便于理解需要看一看2.宽字节注入现在已经很少见,因为如今的编码大多使用utf-8常见url编码:空格–%20′–%27#–%23\–%5c0x02原理我们注入时都会简单输入一个’或者”,进行测试,如果数据库过滤不严格就会产生报错

    2022年10月14日
    2
  • 华为的OD,值得去吗?「建议收藏」

    华为的OD,值得去吗?「建议收藏」最近有不少小伙伴接到了华为OD的面试邀约,但搞不清楚OD到底怎么回事儿,要不要去。所以今天来说说华为的OD到底是怎么回事儿,怎么判断是否值得去。1、华为的OD是怎么回事儿OD,是OutsourcingDispacth的缩写,简单粗暴地讲,就是外包派遣,劳务派遣。基本模式是这样的: A公司是外包公司(或劳务派遣公司,或人力资源公司); A公司签了一堆人,程序…

    2022年7月17日
    117

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号