classpath*: 和classpath:有什么区别_我们可以从Java“HelloWorld”中学到什么?
这是每个Java程序员都知道的程序。它很简单,但是简单的开始可以导致对更复杂概念的深入理解。在这篇文章中,我将探讨从这个简单的程序中学到什么。
公共 类 HelloWorld {
/ **
* @参数参数
* /
public static void main (String [ ] args ) {
// TODO自动生成的方法存根
System。出来。println (“ Hello World” );
} }
1.为什么一切都从一堂课开始?
Java程序是从类构建的,每个方法和字段都必须在一个类中。这是由于它具有面向对象的功能:一切都是一个对象,它是一个类的实例。相对于功能性编程语言,面向对象的编程语言具有很多优势,例如更好的模块化,可扩展性等。
2.为什么总是有“主要”方法?
“ main”方法是程序入口,它是静态的。“静态”表示该方法是其类的一部分,而不是对象的一部分。
这是为什么?我们为什么不将非静态方法作为程序入口?
如果方法不是静态的,则需要先创建一个对象才能使用该方法。因为必须在对象上调用该方法。为了进入目的,这是不现实的。没有鸡肉,我们就无法获得鸡蛋。因此,程序进入方法是静态的。
参数“ String [] args”指示可以将字符串数组发送到程序以帮助程序初始化。
3. HelloWorld的字节码
为了执行该程序,首先将Java文件编译为存储在.class文件中的Java字节码。字节码是什么样的?字节码本身不可读。如果我们使用十六进制编辑器,则如下所示:
我们可以在上面的字节码中看到很多操作码(例如CA,4C等),每个操作码都有一个对应的助记码(例如,在下面的示例中为aload_0)。操作码不可读,但是我们可以使用javap来查看.class文件的助记符形式。
“ javap -c”打印出该类中每个方法的反汇编代码。反汇编代码表示组成Java字节码的指令。
javap -classpath。-c HelloWorld
从“ HelloWorld.java”编译而成的公共 类 HelloWorld 扩展了 Java。郎。对象{ public HelloWorld ();
代码:
0 : aload_0
1 : 调用特殊#1 ; //方法java / lang / Object。“ <init>” :()V
4 : 返回
公共 静态 无效主( java中。郎。字符串[ ] );
代码:
0 : 静态#2 ; //字段java / lang / System.out:Ljava / io / PrintStream;
3 : ldc#3 ; // String Hello World
5 : invokevirtual#4 ; //方法java / io / PrintStream.println:(Ljava / lang / String;)V
8 : return }
上面的代码包含两种方法:一种是默认的构造函数,由编译器推断出来;另一种是默认的构造函数。另一种是主要方法。
在每种方法之下,都有一系列指令,例如aload_0,invokespecial#1等。可以在Java字节码指令列表中查找每个指令的作用。例如,aload_0将局部变量0的引用加载到堆栈上,getstatic获取类的静态字段值。请注意,在getstatic指令指向运行时常量池之后,将显示“#2”。常量池是JVM运行时数据区域之一。这使我们看一下常量池,可以使用“ javap -verbose”命令来完成。
此外,每个指令都以数字开头,例如0、1、4等。在.class文件中,每个方法都有一个对应的字节码数组。这些数字对应于存储每个操作码及其参数的数组的索引。每个操作码的长度为1个字节,指令可以具有0个或多个参数。这就是为什么这些数字不连续的原因。
现在,我们可以使用“ javap -verbose”进一步看一看该类。
javap -classpath。详细的HelloWorld
从“ HelloWorld.java”编译而成的公共 类 HelloWorld 扩展了 Java。郎。对象
SourceFile : “ HelloWorld.java”
次要版本: 0
主要版本: 50
常量池:const#1 = Method #6。#15 ; // java / lang / Object。“ <init>” :()V const#2 = 字段 #16。#17 ; // java / lang / System.out:Ljava / io / PrintStream;const#3 = 字符串 #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 = ASCII码; const#10 = Asciz LineNumberTable ; const#11 = Asciz主函数;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你好世界; const#19 = 类别 #26 ; // java / io / PrintStreamconst#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 = ASCII输出; const#25 = Asciz Ljava / io/ PrintStream ;; const#26 = Asciz java / io / PrintStream ; const#27 = Asciz println ; const#28 = Asciz ( Ljava / lang / String ; ) V ;
{ 公共 HelloWorld ();
代码:
堆栈= 1,Locals = 1,Args_size = 1
0 : aload_0
1 : invokespecial#1 ; //方法java / lang / Object。“ <init>” :()V
4 : 返回
LineNumberTable :
第2行: 0
公共 静态 无效主( java中。郎。字符串[ ] );
代码:
堆栈= 2,Locals = 1,Args_size = 1
0 : getstatic#2 ; //字段java / lang / System.out:Ljava / io / PrintStream;
3 : ldc#3 ; // String Hello World
5 : invokevirtual#4 ; //方法java / io / PrintStream.println:(Ljava / lang / String;)V
8 : 返回
LineNumberTable :
行9 : 0
行10 : 8 }
从JVM规范开始:运行时常量池的功能类似于常规编程语言的符号表,尽管它包含的数据范围比典型的符号表还大。
“ invokespecial#1”指令中的“#1”指向常量池中的#1常量。该常量为“方法#6.#15;”。从数字中,我们可以递归获得最终常数。
LineNumberTable向调试器提供信息,以指示Java源代码的哪一行对应于哪个字节代码指令。例如,Java源代码中的第9行对应于main方法中的字节代码0,而行10对应于字节代码8。
如果您想了解更多有关字节码的信息,可以创建并编译一个更复杂的类以进行查看。HelloWorld确实是这样做的起点。
4.如何在JVM中执行?
现在的问题是,JVM如何加载类并调用main方法?
在执行main方法之前,JVM需要1)加载,2)链接和3)初始化类。1)加载将类/接口的二进制形式带入JVM。2)链接将二进制类型的数据合并到JVM的运行时状态中。链接包括3个步骤:验证,准备和可选的解决方案。验证可确保类/接口在结构上正确;准备工作涉及分配类/接口所需的内存;分辨率解析符号引用。最后3)初始化为类变量分配了适当的初始值。
此加载作业由Java类加载器完成。启动JVM时,将使用三个类加载器:
1. Bootstrap类加载器:加载位于以下位置的核心Java库: / jre / lib目录。它是核心JVM的一部分,并用本机代码编写。
2. 扩展类加载器:将代码加载到扩展目录中(例如, / jar / lib / ext)。
3. 系统类加载器:加载在CLASSPATH上找到的代码。
因此,HelloWorld类由系统类加载器加载。当main方法执行时,它将触发其他依赖类的加载,链接和初始化(如果存在)。
最后,将main()框架压入JVM堆栈,并相应地设置程序计数器(PC)。PC然后指示将println()帧推送到JVM堆栈。当main()方法完成时,它将从堆栈中弹出并执行完毕。
最后,开发这么多年我也总结了一套学习Java的资料与面试题,如果你在技术上面想提升自己的话,可以关注我,私信发送领取资料或者在评论区留下自己的联系方式,有时间记得帮我点下转发让跟多的人看到哦。
classpath*: 和classpath:有什么区别_我们可以从Java“HelloWorld”中学到什么?相关推荐
- java跟c 的区别_【c++跟java的区别】java跟c语言的区别
Java与C/C++作为编程语言的两大巨头,他们有什么区别呢?下面是小编为大家准备的c++跟java的区别,希望大家喜欢! c++的定义 C++是一种面向对象的计算机程序设计语言.C++这个词在中国大 ...
- java主线程和子线程区别_主线程异常– Java
java主线程和子线程区别 Being a Java Programmer, you must have seen exception in thread main sometimes while r ...
- java comp env 区别_加和不加java:comp/env/前缀有什么区别?
java:comp/env是标准的J2EE环境查找规则 使用这种方式必须做一次环境名到JNDI名的映射 这种隔离使得在写程序时不必关注真正的JNDI名字 其实说白了跟把JNDI名放到配置文件里是一样的 ...
- java和脚本语言 区别_脚本语言和java语言有什么不同
分析原因:快捷方式的打开方式被病毒等修改了! 将下面的代码保存为 .reg 然后双击运行,选择导入即可! Windows Registry Editor Version 5.00 [HKEY_CLAS ...
- web.xml 配置中classpath: 与classpath*:的区别
首先 classpath是指 WEB-INF文件夹下的classes目录 (1)什么事classes目录?classes就是: 1.存放各种资源配置文件 eg.init.properties log ...
- Java和pathion_Spring配置中的classpath:与classpath*:的区别
概念解释及使用场景: classpath是指WEB-INF文件夹下的classes目录. 通常我们一般使用这种写法实在web.xml中,比如spring加载bean的上下文时,如下: contextC ...
- Spring配置中的classpath:与classpath*:的区别研究
文章目录 概念解释及使用场景 classpath:和classpath*:区别 概念解释及使用场景 classpath是指WEB-INF文件夹下的classes目录. 通常我们一般使用这种写法实在we ...
- web.xml配置中classpath:与classpath*:的区别
classpath是指 WEB-INF文件夹下的classes目录 解释classes含义: 1.存放各种资源配置文件 eg.init.properties log4j.properties stru ...
- 4、Spring配置中的classpath:与classpath*:的区别
2019独角兽企业重金招聘Python工程师标准>>> 一.概念解释及使用场景: classpath是指WEB-INF文件夹下的classes目录. 通常我们一般使用这种写法实在we ...
最新文章
- cocoa 坑爹的委托
- 搭建prometheus+grafana监控系统
- 【译】 Web Components 的高级工具
- mysql查询锁表语句和kill对应的线程
- 2.2.5 操作系统之调度算法(时间片轮转调度算法、优先级调度算法、多级反馈队列调度算法)
- Java技术分享:Lambda表达式之接口实例化
- MySQL双主(主主)架构方案
- OpenJudge:熄灯问题
- 关于JSP与Int不得不说的故事
- cad文件管理服务器,CAD文件管理(ZT)
- 初识STM32F103
- RC串联延时电路电容充电时间计算
- python输入年份判断生肖_python年份判断生肖
- POJ 3422 Kaka's Matrix Travels(拆点+最大费用流)题解
- 我的世界服务器怎么做无限的弓,我的世界怎么用命令方块做无限弓?
- 2022年第十七届研电赛报名|安谋科技(Arm China)命题:基于特定开发平台的理性智能体设计
- z-index的使用小结
- 程序员怎么接单赚外快,去这6个平台就可以了!
- 【JUC高并发编程】—— 初见JUC
- 【OSPF的特殊区域和特性】ospf的lsdb优化、特殊区域、路由汇总、静默接口、ospf报文认证、LSA路由汇总、高级特性(PRC、智能计时器、FRR、ospf database overflow)
热门文章
- 在SAP分析云里利用词云技术显示大段文本里的关键词
- 小技巧,找出所有check table设置为某个数据库表的数据库表
- HubSpot company数据在UI上的展示和通过API方式进行获取
- SAP Fiori 修改catalog group名称的技术实现
- automatic asynchronous creation if no note exists
- Appointment get entity debug
- why we need a undefined parameter in function signature
- How is navigation target url request handled by backend
- 打印某个user在指定时间段内做过的personalization detail
- Cloud for Customer里的Shell menu manager