在程序员的世界中,你总会听到一句“PHP是世界上最好的语言”的调侃。然而在你进入软件程序开发之后,你会发现即使开发语言千千万,最盛行的还是JAVA。从淘宝的技术变迁中我们可以见一些端倪,早期电商刚起来的时候,那会儿的互联网还很简单,使用PHP+Mysql+Apache+Linux就可以快速搭建起一套电商系统,但随着电商平台、支付平台的完善,网上购物开始变得简单,越来越多的人使用淘宝购物了,淘宝的技术架构也开始不断的升级,增加服务器数量来提高系统可用性。

通过运维手段扩充资源是一种方式,治标不治本,最根本的原因还是在于PHP这种语言可扩展性不够,用户量十万、百万、千万的时候都还能支撑,但到了上亿、亿万的时候怎么扩展都不行了。于是淘宝系统开始一点点的前后端分离,后端使用JAVA语言开发,逐渐迁移业务。现在我们所使用的淘宝系统,80%以上的后端程序都是Java开发,可见笑到最后才是赢家啊。不过JAVA语言的上手难度就比PHP、前端高很多了,所以今天我们给大家讲解下一行JAVA代码到底是如何运行起来的,JAVA后浪们可以以此为入门Java的基础,开启Java开发、人生赢家之路

Java是一种半解释型语言,相对的有解释型语言Python&PHP、编译型语言C&C++。解释型语言说的是只需要在客户端输入代码后就可以运行起来,实时看到结果,编译型语言说的是源代码需要进行构建编译成二进制文件才能在机器运行起来,半解释型语言介于其中,它把输入的代码进行编译,编译后在JVM虚拟机中运行(注:JVM虚拟机是在实际的机器中运行的)。半解释型语言的好处就是可以跨平台,一次编译,多次执行

我们通过下面这边Java程序,来讲明Java程序从编译到最后运行到整个流程。JVM运行Java程序有两种方式,分别是jar包和Class类文件,jar包是偏上层的方式,把所有程序都打包成一个jar包,便于交付测试人员测试、运维人员发布,它的运行逻辑是通过java.exe找到java自带的GetMainClassName函数,该函数获取JNIENV实例,并调用JarFileJNIENV实例中的GetMainfest()函数获取MainClass函数,Main函数再调用Java.c中的LoadClass方法加载主类。

而Class方式则是越过上层,直接通过main函数调用Java.c中的LoadClass方法装载类。所以说jar运行的方式本质上也是class类运行的方式,因此我们来关注如何类方式如何加载运行就好了。下面代码想实现的功能是打印Code这个字符,整体代码如下。我们先定义了一个类HelloJava,在这个类新建了一个对象去打印Code字符,而这个对象又调用了类Product.java

在整个代码的运行中,包含两步,第一步是编译,第二步是运行。源文件创建完之后,使用javac就可以编译.java程序,程序会被编译成.class文件,使用java命令就可以运行.class文件。编译后的文件有代码中出现过的类名&变量名&方法引用名、类中各个方法的字节码,它们分别存储在常量池、方法字节码中。

在Java程序的编译过程中,如果该类所依赖的类还没有被编译,编译器就会先编译被依赖的类,如果依赖类编译了则直接引用。在Java类的运行中,包含加载和运行两个步骤。.class文件就是通过类加载器到jvm当中的。在Java中默认有三种类加载器,从下往上依次是自定义类加载器UserClassLoader(负责加载自定义的class文件)、应用类加载器AppClassLoader(负责加载classpath指定的jar包和目录中的class文件)、扩展类加载器ExClassLoader(负责加载Java平台中扩展功能的jar包)、启动类加载器BootstrapClassLoader(负责加载$JAVA_Home中jre/lib/rt.jar中所有的class类)。当AppClassLoader接收到一个类加载命令后,它不会自己先去加载,而是给到扩展类加载器,同样扩展类加载器自己也不会先去加载类,而是把它给到启动类加载器去加载,如果失败再层层往下传递。所以Java是动态在加载类。

回到我们刚刚的例子中,在编译好Java程序后,我们得到HelloJava.class文件,在终端我们输入javaHelloJava,系统就会启动一个JVM进程,JVM进程从classpath的路径中寻找命名为HelloJava.class的二进制文件,将HelloJava的类加载信息加载到运行时数据区的方法区,找到HelloJava的主函数入口,执行Main函数。Main函数的第一条命令是Productproduct = newProduct(“Code”),它需要JVM创建一个Product对象,但此时方法区中没有没有Product类的信息,于是JVM加载Product类,把Product类的类型信息放在方法区中。加载完了Product类之后,JVM虚拟机在堆区为新的Product实例分配内存,初始化类。在调用product.printName()方法的时候,JVM根据Product引用找到Product对象,根据Product对象持有的引动定位到方法区中的Animal类的类型信息方法表,获取printName()函数的字节码地址,运行printName()函数,打印出来“Code”。

微观的编译执行介绍完了,我们来看看中观的执行。在介绍Java是解释型语言时,我们有讲到JVM是跨平台执行的,也就是一份Java代码编译之后,可以在Linux、unix、Windows、Macos等操作系统平台中执行。我们一起来看看是如何实现的呢?在Java程序运行中有三个概念,JVM、JDK、JRE

  • 所谓JVM就是Javavirtual Machine,Java虚拟机,执行Java代码;
  • 所谓JDK是指的JavaDevelopment kit,Java开发工具包,Java开发人员使用;
  • 所谓JRE就是JavaRuntimeEnvironment,Java运行时环境。

JVM属于JRE,JRE属于JDK。在JDK的安装中,有不同的版本,比如Linuxx86、Windowsx64,只要安装了JDK之后,就由JDK来区分操作系统,JVM是运行在操作系统之上,区分操作系统的任务就是由JDK来完成的,只要你的电脑装了JDK,任何一份Class字节码都会运行在JVM中,JVM又可以运行在任意操作系统中,从而实现了“跨平台一次编译,多次执行”。

讲完了中观的执行,我们来看看宏观执行。我们程序员在写Java代码时,都会把程序编译成jar包,通过jar包来运行程序。一个jar包代表了一个功能模块的实现,如果某个jar包有我们想要使用的功能,就在程序中引用就好。然而业务功能在开发实现时可运行依赖的jar包很多,如果把每个功能所实现的jar包都放在自己的jar包中,就会非常的浪费资源和运行效率。这时候我们可以把程序依赖的jar包都放在一个单独的文件夹中,然后修改jar包中“META-INF”目录下的“MANIFEST.MF”清单文件即可。在manifest文件中,我们指定Manifest文件的版本,运行主类的名称,程序所依赖的jar包的Classpath路径都写明清楚,Java程序执行时加载manifest文件即可。

本文详细的介绍了一行JAVA代码是如何在JVM系统中运行起来的,对于有志加入互联网行业,使用Java语言开发贡献力量的朋友们来说,可以在初学时深刻的理解体会到Java代码时怎么运行起来的、JDK&JRE&JVM是什么?在面试的时候也能比较轻松从容的回到面试官问题,在带新人的时候也可以装一把大佬。码字不易,赶紧收藏起来这份Java宝典吧,如果你愿意,点个在看和喜欢,把它也传递给你的伙伴们喔~

java main函数_一行JAVA代码如何运行起来?相关推荐

  1. Java main方法_解释Java中的main方法,及其作用_一个java文件中可包含多个main方法

    public static void main(String[] args) {} 或者 public static void main(String args[]) {} main方法是我们学习Ja ...

  2. java main函数_都知道Java程序的入口方法是main,那你知道为什么是main方法吗?

    我们都知道Java的入口方法是main函数,下面这段代码就是Java中非常经典的Hello World代码: 我们通过Java提供的工具进行编译执行: 通过上面的代码我们知道Java入口方法的几个要求 ...

  3. python join函数_一行 Python 代码能实现这么多丧心病狂的功能?

    最近看知乎上有一篇名为<一行 Python 能实现什么丧心病狂的功能?>(https://www.zhihu.com/question/37046157)的帖子,点进去发现一行Python ...

  4. java skip函数_【Java必修课】图说Stream中的skip()和limit()方法及组合使用

    1 简介 本文将讲解Java 8 Stream中的两个方法:skip()和limit().这两个方法是Stream很常用的,不仅各自会被高频使用,还可以组合出现,并能实现一些小功能,如subList和 ...

  5. 用python编写一个求偶数阶乘的函数_一行Python代码写阶乘函数

    原标题:一行Python代码写阶乘函数 背景 我以前用Dart写过一行的阶乘函数: fact(double n) => n < 0 ? throw ('n must be bigger t ...

  6. java matcher函数_在Java正则表达式中使用Matcher.end()方法

    方法java.util.regex.Matcher.end()返回根据正则表达式从序列中匹配最后一个字符后的偏移值.此方法不需要任何参数.如果没有匹配发生,或者匹配操作失败,则抛出IllegalSta ...

  7. java string()函数_从Java中的String函数返回String构建器?

    我有以下程序,我必须将字符串附加到另一个字符串,我使用字符串构建器以标准方式执行.但是,即使在将其转换为toString()之后,该函数也不允许我返回ab.我想问为什么? import java.ut ...

  8. java string()函数_转载java String.split()函数的用法详解

    转载java String.split()函数的用法详解 如果您发现本文排版有问题,可以先点击下面的链接切换至老版进行查看!!!在java.lang包中有String.split()方法的原型是: p ...

  9. java 模板函数_重温Java中的模板方法设计模式

    Java 8 lambda表达式的简洁性为经典的GoF设计模式提供了新的视角.通过利用函数式编程,我们可以通过更少的耦合获得相同的好处 - 模板方法就是一个很好的例子. 经典的GoF模板方法实现 模板 ...

最新文章

  1. hdu 5059 判断数字表示方式以及范围合法(int型之内)
  2. 摩根士丹利华鑫基金公司面试
  3. Java基础篇:泛型与类型擦除
  4. elementUI的container布局设置全屏宽度
  5. 43. Know how to access names in templatized base classes.
  6. TCP/IP协议-三次握手四次挥手
  7. Linux下输入法切换快捷键设置
  8. Python数据探索性分析和预处理
  9. php 786.00,美國佛羅裡達州區號786
  10. 黑鲨helo支持html吗,黑鲨游戏手机Helo发布 张大仙公布私人配置
  11. opencv-python图像孔洞填充
  12. 计算机文化基础案例教程第三版答案,计算机文化基础案例教程教学课件作者第3版谭宁教学课件素材排骨做法.doc...
  13. 安装Mosquitto学习MOTT协议
  14. 前端面试总结2020年9月12家面试
  15. jQuery 中的 39 个技巧
  16. Springcloud HRM微服务项目(二)
  17. 计算机网络—自顶向下 计算机网络和因特网
  18. 非谓语动词doing作主语/宾语
  19. 基于C#的超市收银管理系统
  20. 实训可视化项目小结 --- 开启Python初始之旅

热门文章

  1. 【数据结构与算法】双链表V2.0的Java实现
  2. linux 命令记录
  3. 高级Java面试题,你敢挑战吗?
  4. rmdir命令--Linux命令应用大词典729个命令解读
  5. Apache开启Gzip压缩设置(转)
  6. Android 4.0操作系统的20个使用小技巧
  7. PL/SQL -- DML 触发器
  8. 选防晒霜 要看四个要点 - 健康程序员,至尚生活!
  9. 漏洞挖掘、漏洞分析和漏洞利用
  10. C/C++编程笔记:输入输出的优化,你还为思路正确却TLE而烦恼吗?