Java的运行原理(转载)
在Java中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟的机器。这台虚拟的机器在任何平台上都提供给编译程序一个的共同的接口。编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由解释器来将虚拟机代码转换为特定系统的机器码执行。在Java中,这种供虚拟机理解的代码叫做字节码(ByteCode)(class文件的内容),它不面向任何特定的处理器,只面向虚拟机。每一种平台的解释器是不同的,但是实现的虚拟机是相同的。Java源程序经过编译器编译后变成字节码,字节码由虚拟机解释执行,虚拟机将每一条要执行的字节码送给解释器,解释器将其翻译成特定机器上的机器码,然后在特定的机器上运行。
跨平台:
话说,在北京,一般都是讲北京话的,上海,一般都是将上海话,广东,广东话...
现有一公文发出,要全国执行,该当如何?——先统一翻译成普通话。各地在将普通话版本翻译成当地的方言。
这里,北京、上海就是不同类型的机器windows,linux...
编译(javac)就是将公文翻译成普通话的过程,而编译出的.class文件,就是公文的普通话版本。
在执行的时候,各地的翻译就是jvm,负责将.class转换成本地能够理解的方言来执行。
*.java→*.class→机器码 java编译器 (编译) → 虚拟机(解释执行) → 解释器(翻译) → 机器码 |
Java虚拟机(JVM)
Java虚拟机(JVM)是Java Virtual Machine的缩写,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能模拟来实现的。
Java中,类加载器把一个类装入JAVA虚拟机需要经过三个步骤来完成:装载、链接、初始化,其中链接又分来校验、准备、解析过程
装载:查找和导入.class文件
链接:检查装入.class文件的正确性,然后,java虚拟机为变量分配内存,设置默认值
初始化:把符号引用变成直接引用。。。
public class Main { private static int size=1; public static void main(String args[]) { User u = new User(); u.setName("李文水"); u.setPwd("159"); String name = u.getName(); String pwd = u.getPwd(); u = null; } } public class User { private String name; private String pwd; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } }
现在假设这两个java源文件已经被编译成了CLASS文件了,我们来看看java虚拟机怎么执行的。
Java虚拟机工作流程:
1.装载
描叙:Java虚拟机装载指定的CLASS文件
结果:形成这个CLASS类的实例对象
过程:java虚拟机使用类装载器定位到相应的CLASS文件,然后读取这个CLASS文件(一个线性二进制数据流),将它传入java虚拟机中。紧接着虚拟机提取其中的类型信息。比如:该类的类名,方法名,变量名,修饰符,方法的返回类型等等。还有一个重要的东西就是常量池。(常量池保存了该类型的所有常量,包括直接常量和对其他类型,字段,方法的符号引用)将这些信息保存在一个叫做方法区的地方。最终形成CLASS类的实例,这个实例存放在内存的堆区。它成为了java程序与内部数据结构之间的接口,程序要访问该类型的信息,程序就调用该类型对应的CLASS实例对象的方法。简而言之:这个过程就是把一个类型的二进制数据解析为方法区中的内部数据结构,并在堆上建立一个CLASS对象的过程。
示例:装载Main类
Java虚拟机读取Main类的CLASS文件,生产对应的java.lang.Class类的实例,读取其中的类型信息,比如修饰符 private,public,static,另外变量 size,name,pwd,User(User即为一个引用)共同构成了这个类的常量池。将这些信息保存在方法区,
2.链接
描述:验证,准备,解析(可选)
结果:这个类型是正确的。(这里不知道该怎么描述)
过程:
1)验证:确定类型符合java语言的语义,比如:final类不能有子类,final方法不能被覆盖,确保在类型和超类型之间没有不兼容的方法声明(比如两个方法拥有同样的名字,参数完全相同,但返回类型不同)。
2)准备:java虚拟机为类变量分配内存,设置默认值
3)解析:在类型的常量池中寻找类,接口,字段和方法的符合引用把这些符号引用替换成直接引用的过程。
示例: 连接Main类
Java虚拟机为size分配内存,并赋默认值0.找到常量池中User类的引用,如果User类还没有被装载,则装载并且连接该类,然后将常量池中对User类的引用替换为直接引用。在此时User类并不会被初始化,因为还没有用它。
3.初始化
描述:初始化一些静态变量
结果:这个类型可以使用了
过程:可能会调用()方法,(这个方法只能够由java虚拟机调用)来初始化该类的静态变量。在调用这个方法前,必须确认该类的超类的() 方法已经被调用。
示例:初始化Main类
Java虚拟机将Main类的静态变量赋值为1.
4.使用(执行该类代码了)
1.User u = new User();(存放在内存的堆区)
创建了一个User类实例,实际上是通过这个类的CLASS实例实例化的。方法如下:
User u=(User)Class.forName("User").newInstance();
为了方便,用C代替Class.forName("User")
2.u.setName("李文水"); u.setPwd("159");
调用该类的方法,为该类的变量赋值,Java虚拟机内部调用是这样的,通过方法区找到该方法,利用CLASS实例的如下方法调用:
c.getMethod("setName").invoke(u,"李文水");
3.String name = u.getName(); String pwd = u.getPwd();
与第二步类似,不同的是将取得的值分别赋给了变量name和pwd。关键是这个值保存在哪里?和实例对象一样,存放在堆区。这个时候我应该可以看出CLASS实例的作用了,它就是起个中间作用,将程序中的调用反应到堆区上数据的变化。
4.u = null;
这个步骤写出来的目的是了解一下Java虚拟机垃圾回收机制。(没有什么实际意义)
Java虚拟机内部会根据一种规则(这个对象是否可以触及)来判断这两个类是否可以回收了?具体形式如下:
当执行 u = null;时这条线就被斩断了,因此User实例就不可以触及了,所以java虚拟机就可以回收这个User实例了
Java的运行原理(转载)的更多相关文章
- Java基础知识强化之多线程笔记05:Java程序运行原理 和 JVM的启动是多线程的吗
1. Java程序运行原理: Java 命令会启动Java 虚拟机,启动 JVM,等于启动了一个应用程序,也就是启动了一个进程.该进程会自动启动一个 “主线程” ,然后主线程去调用某个类的 m ...
- [零] Java 语言运行原理 JVM原理浅析 入门了解简介 Java语言组成部分 javap命令使用
Java Virtual Machine 官方介绍 Java虚拟机规范官方文档 https://docs.oracle.com/javase/specs/index.html 其中以java8的为 ...
- Java基础-运行原理及变量(01)
java运行原理 手动编写java文件由编译器编译成.class文件,再由解释器翻译class文件成机器语言运行. Java中注释分类 单行注释格式: //注释文字多行注释格式: /* 注释文字 */ ...
- Java的运行原理
在Java中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟的机器.这台虚拟的机器在任何平台上都提供给编译程序一个的共同的接口.编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由 ...
- Java程序运行原理分析
class文件内容 class文件包含Java程序执行的字节码 数据严格按照格式紧凑排列在class文件的二进制流,中间无分割符 文件开头有一个0xcafebabe(16进制)特殊的标志 JVM运行时 ...
- Java程序运行原理
概念介绍: ![file](https://img2018.cnblogs.com/blog/1454321/202001/1454321-20200104145655999-149562495.jp ...
- SpringMVC学习(二)——SpringMVC架构及组件(及其运行原理)-转载
相信大家通过前文的学习,已经对SpringMVC这个框架多少有些理解了.还记得上一篇文章中SpringMVC的处理流程吗? 这个图大致描述了SpringMVC的整个处理流程,这个流程图还是相对来说比 ...
- Java基础—Java运行原理
Java程序运行原理 在Java中引入了虚拟机(JVM,Java Virtual Machine)的概念,即在机器和编译程序之间加入了一层抽象的虚拟的机器.虚拟机在任何平台上都提供给编译程序一个的共同 ...
- Java自学成长路线(转载)
JAVA自学之路 一:学会选择 决心做软件的,大多数人选的是java,或是.net,也有一些选择了手机.嵌入式.游戏.3G.测试等. JAVA是一种平台,也是一种程序设计语言,如何学好程序设计不仅 ...
随机推荐
- kali自定义分辨率(1920*1080)
运行一下两行代码: xrandr --newmode -hsync +vsync xrandr --addmode Virtual1 "1920x1080_60.00"
- go语言的运算符
什么是运算符:运算符用于在程序运行时执行数学或逻辑运算 go语言的运算符如下: 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 其他运算符 一,算数运算符 运算符 描述 实例 + 相加 A ...
- 理解RNN
摘自:https://zybuluo.com/hanbingtao/note/541458 语言模型就是这样的东西:给定一个一句话前面的部分,预测接下来最有可能的一个词是什么. 语言模型是对一种语言的 ...
- SpringCloud-分布式配置中心(基于SpringBoot2.X)
一.配置中心的作用:可以将多种应用的配置进行集中式的管理,将这些配置统一存放到git或svn里面存储: 二.搭建SpringCloud-Config-Server 2.1如图后续步骤勾选Config ...
- Paper | 学习多任务中的最佳分/ 合结构(十字绣结构)
目录 1. 问题 2. 十字绣结构(Cross-stitch architecture) 3. 实验设计 论文:Cross-stitch Networks for Multi-task Learnin ...
- Redis sentinel之集群搭建
环境 由于不太熟悉docker,所以,把docker当虚拟机来用,服务器环境如下: Redis Server 环境搭建 Redis Server 01 搭建 并且制作Redis镜像 容器建立 # do ...
- Thread,ThreadPool,Task
线程分为前台和后台.比如我们直接new一个Thread这就是前台线程. 前台线程一定会执行. 比如我们创建2个线程:1号,2号,同时执行,假设1号是主线程,1执行完了,依旧会等待2执行完成,整个程序才 ...
- <笔记>原生PHP访问TP模板变量
在模板中,原生PHP可以直接访问模板变量,不过如果模板变量是数组,要访问数组中元素时不能使用"."符号,只能通过数组['元素名']的方式
- Leetcode_5.最长回文子串
最长回文子串 题目描述: 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad" 输出: "bab& ...
- 【Solidity】学习(2)
address 地址类型 40个16进制数,160位 地址包括合约地址和账户地址 payable 合约充值 balance,指的是当前地址的账户value,单位是wei this指的是当前合约的地址 ...