Java、Python与PHP的虚拟机异同

Java-JVM

定义

JDK(Java Development Kit) 是 Java 语言的软件开发工具包(SDK)。JDK 物理存在,是 programming tools、JRE 和 JVM 的一个集合

JRE(Java Runtime Environment)Java 运行时环境,JRE 物理存在,主要由Java API 和 JVM 组成,提供了用于执行 java 应用程序最低要求的环境。

JVM(Java Virtual Machine) 是一种软件实现,执行像物理机程序的机器(即电脑)。JVM 通过执行 Java bytecode 可以使 java 代码在不改变的情况下运行在各种硬件之上。JVM是基于栈的。

JVM 执行

加载代码

验证代码

执行代码

提供运行环境

JVM 生命周期

启动:任何一个拥有main函数的class都可以作为JVM实例运行的起点

运行:main函数为起点,程序中的其他线程均有它启动,包括daemon守护线程和non-daemon普通线程。daemon是JVM自己使用的线程比如GC线程,main方法的初始线程是non-daemon。

消亡:所有线程终止时,JVM实例结束生命。

JVM结构及内存模型

名词解释:

Class Loader:类加载器负责加载程序中的类型(类和接口),并赋予唯一的名字。为什么使用双亲委托模型——ClassLoader 隔离问题。

Execution Engine:执行引擎。执行引擎以指令为单位读取 Java 字节码。它就像一个 CPU 一样,一条一条地执行机器指令。

Runtime Data Areas::运行时数据区。

PS:想起面试的时候被问到过这样的问题:你在使用java过程中是否遇到过OOM的情况?当时一阵懵比。现在总结下:

PC寄存器(PC Register)是唯一一个在 Java 虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

JVM 栈(Java Virtual Machine Stack):如果JVM Stack可以动态扩展,但是在尝试扩展时无法申请到足够的内存去完成扩展,或者在建立新的线程时没有足够的内存去创建对应的虚拟机栈时抛出。

本地方法栈(Native method stack):如果本地方法栈可以动态扩展,并且扩展的动作已经尝试过,但是目前无法申请到足够的内存去完成扩展,或者在建立新的线程时没有足够的内存去创建对应的本地方法栈,那Java虚拟机将会抛出一个OutOfMemoryError异常。

方法区(Method area):如果方法区的内存空间不能满足内存分配请求,那Java虚拟机将抛出一个OutOfMemoryError异常。

运行时常量池(Runtime constant pool):当创建类和接口时,如果构造运行时常量池所需的内存空间超过了方法区所能提供的最大内存空间后就会抛出OutOfMemoryError

堆(Heap):如果实际所需的堆超过了自动内存管理系统能提供的最大容量时抛出。

总结一下就是无法申请到足够的内存以及超出最大容量两方面原因

垃圾回收

新生代

新生代由 Eden 与 Survivor Space(S0,S1)构成,大小通过-Xmn参数指定,Eden 与 Survivor Space 的内存大小比例默认为8:1,可以通过-XX:SurvivorRatio 参数指定,比如新生代为10M 时,Eden分配8M,S0和S1各分配1M。

Eden:希腊语,意思为伊甸园,在圣经中,伊甸园含有乐园的意思,根据《旧约·创世纪》记载,上帝耶和华照自己的形像造了第一个男人亚当,再用亚当的一个肋骨创造了一个女人夏娃,并安置他们住在了伊甸园。

大多数情况下,对象在Eden中分配,当Eden没有足够空间时,会触发一次Minor GC,虚拟机提供了-XX:+PrintGCDetails参数,告诉虚拟机在发生垃圾回收时打印内存回收日志。

Survivor:意思为幸存者,是新生代和老年代的缓冲区域。

当新生代发生GC(Minor GC)时,会将存活的对象移动到S0内存区域,并清空Eden区域,当再次发生Minor GC时,将Eden和S0中存活的对象移动到S1内存区域。

存活对象会反复在S0和S1之间移动,当对象从Eden移动到Survivor或者在Survivor之间移动时,对象的GC年龄自动累加,当GC年龄超过默认阈值15时,会将该对象移动到老年代,可以通过参数-XX:MaxTenuringThreshold 对GC年龄的阈值进行设置。

老年代

老年代的空间大小即-Xmx 与-Xmn 两个参数之差,用于存放经过几次Minor GC之后依旧存活的对象。当老年代的空间不足时,会触发Major GC/Full GC,速度一般比Minor GC慢10倍以上。

永久代

在JDK8之前的HotSpot实现中,类的元数据如方法数据、方法信息(字节码,栈和变量大小)、运行时常量池、已确定的符号引用和虚方法表等被保存在永久代中,32位默认永久代的大小为64M,64位默认为85M,可以通过参数-XX:MaxPermSize进行设置,一旦类的元数据超过了永久代大小,就会抛出OOM异常。

虚拟机团队在JDK8的HotSpot中,把永久代从Java堆中移除了,并把类的元数据直接保存在本地内存区域(堆外内存),称之为元空间。

这样做有什么好处?

有经验的同学会发现,对永久代的调优过程非常困难,永久代的大小很难确定,其中涉及到太多因素,如类的总数、常量池大小和方法数量等,而且永久代的数据可能会随着每一次Full GC而发生移动。

而在JDK8中,类的元数据保存在本地内存中,元空间的最大可分配空间就是系统可用内存空间,可以避免永久代的内存溢出问题,不过需要监控内存的消耗情况,一旦发生内存泄漏,会占用大量的本地内存。

判断垃圾回收

引用计数法:在对象上添加一个引用计数器,每当有一个对象引用它时,计数器加1,当使用完该对象时,计数器减1,计数器值为0的对象表示不可能再被使用。引用计数法实现简单,判定高效,但不能解决对象之间相互引用的问题。

可达性分析法:通过一系列称为 “GC Roots” 的对象作为起点,从这些节点开始向下搜索,搜索路径称为 “引用链”,以下对象可作为GC Roots:

本地变量表中引用的对象

方法区中静态变量引用的对象

方法区中常量引用的对象

Native方法引用的对象

当一个对象到 GC Roots 没有任何引用链时,意味着该对象可以被回收。

垃圾回收算法

标记-清除算法

对待回收的对象进行标记。

算法缺点:效率问题,标记和清除过程效率都很低;空间问题,收集之后会产生大量的内存碎片,不利于大对象的分配。

复制算法

复制算法将可用内存划分成大小相等的两块A和B,每次只使用其中一块,当A的内存用完了,就把存活的对象复制到B,并清空A的内存,不仅提高了标记的效率,因为只需要标记存活的对象,同时也避免了内存碎片的问题,代价是可用内存缩小为原来的一半。

标记-整理算法

在老年代中,对象存活率较高,复制算法的效率很低。在标记-整理算法中,标记出所有存活的对象,并移动到一端,然后直接清理边界以外的内存。

参考文章

Python

PVM

PVM是Python的运行引擎。他通常表现为python系统的一部分。并且他是实际运行脚本的组件。

编译器:将源码编译成运行在虚拟机上执行的opcode(pyc文件),pyc文件是在python虚拟机上执行的一种跨平台字节码。

运行时:虚拟机解释器把opcode(pyc文件)解释成具体机器的机器码,执行。

JVM与PVM

Java代码从源程序到执行,要经过的过程是:编译器(javac)把源代码转化为字节码,然后解释器(Java.exe)把字节码转换为计算机理解的机器码来执行。其中编译器和解释器都是Java虚拟机(JVM)的一部分,由于针对不同的硬件与OS,Java解释器有所不同,因此可以实现“一次编译、到处执行”。所以JVM是Java跨平台特性的关键所在。

对于Python,其源代码到执行也要经过如下过程:源代码--->字节码--->机器码。与Java不同的是,Python使用的虚拟机是基于其他语言实现的,比如我们一般使用的Python实际为Cpython,也就是其虚拟机由C实现,这个虚拟机负责把Python源码编译为字节码,再解释执行。另外,还有Jypython、Ironpython等。

PHP-Zend&HHVM

Zend引擎默认做法,是先编译为opcode,然后再逐条执行,通常每条指令对应的是C语言级别的函数。如果我们产生大量重复的opcode(纯PHP写的代码和函数),对应的则是Zend多次逐条执行这些C代码。

HHVM生成和执行PHP的中间字节码(HHVM生成自己格式的中间字节码),执行时通过JIT(Just In Time,即时编译是种软件优化技术,指在运行时才会去编译字节码为机器码)转为机器码执行。JIT将大量重复执行的字节码在运行的时候编译为机器码,达到提高执行效率的目的。通常,触发JIT的条件是代码或者函数被多次重复调用。

写在最后

时间匆忙,囫囵吞枣,努力完善。

后端开发离不开Java,python和php,深入学习原理,比较异同,最佳使用。

2017.06.23

php和python和java-Java、Python与PHP的虚拟机异同相关推荐

  1. 有java基础的人学python_准备自学Python ,会java,有什么建议吗?

    作为一名IT从业者,我来回答一下这个问题. 首先,对于具有Java编程基础的人来说,学习Python的初期并不会遇到太大的障碍,但是要结合自己的发展规划来制定学习规划,尤其要重视学习方向的选择. Ja ...

  2. python跟java 效率_对比平台--Java与Python之间的性能差异

    ava Performance和Python之间的主要区别 以下是描述Java Performance和Python之间的区别的要点列表: 以下是Java性能与Python之间的主要区别,我们在决定应 ...

  3. java python算法_用Python,Java和C ++示例解释的排序算法

    java python算法 什么是排序算法? (What is a Sorting Algorithm?) Sorting algorithms are a set of instructions t ...

  4. c# typescript_在任何IDE中从C#,Java或Python代码获取TypeScript接口的简单方法

    c# typescript by Leonardo Carreiro 莱昂纳多·卡雷罗(Leonardo Carreiro) 在任何IDE中从C#,Java或Python代码获取TypeScript接 ...

  5. Python, C++和Java代码互翻,Facebook开发首个自监督神经编译器

    译者 | 刘畅 出品 | AI科技大本营(ID:rgznai100) 将早期的编程语言(例如COBOL)的代码库迁移到现在的编程语言(例如Java或C++)是一项艰巨的任务,它需要源语言和目标语言方面 ...

  6. Python一键转Java?“Google翻译”你别闹

    作者 | 若名 出品 | AI科技大本营(ID:rgznai100) 近日,Reddit 上有网友放出了一张疑似 Google 翻译添加了能让编程语言间互相转换的图片,立即引发数千名程序员网友的跟帖热 ...

  7. 学Java还是Python?一张图告诉你!

    Java 和 Python 一直都是两种很火很强大的编程语言,对于刚开始起步学习编程的同学来说,会迷惑且最经常问的问题是,我该学 Java 还是 Python,是不是 Python 容易学,或是应该先 ...

  8. 无监督方法实现C++、Java、Python 代码转换,程序员:出了bug怎么办,两种语言都要看吗?...

    点击上方"视学算法",选择加"星标" 重磅干货,第一时间送达 本文转载自:机器之心  |  参与:魔王 Facebook 提出的无监督代码转换方法 TransC ...

  9. 用AI实现C++、Java、Python代码互译,运行成功率最高达80.9%

    晓查 发自 凹非寺  量子位 报道 | 公众号 QbitAI 还记得美国前一阵要招聘60岁的老程序员吗?都怪编程语言发展太快! 因为新冠疫情的缘故,美国一些地区的失业救济系统不堪重负,而这些系统都是上 ...

  10. 理解java和python类变量以及类的成员变量

    最可怕的不是犯错而是一直都没发现错误,直到现在我才知道自己对类变量的理解有问题. 大概可能也许是因为不常用类变量的原因吧,一直没有发现这个问题**.最近在看C++时才知道了类变量到底是什么**? 以前 ...

最新文章

  1. C++对象的内存分析(2)
  2. c语言编程加密和解密,请问有学长做过这个程序设计的吗?C语言写加密解密问题,跪求代码!...
  3. Java 静态内部类与非静态内部类【复习】
  4. 2019 Multi-University Training Contest 1 - 1011 - Function - 数论
  5. 十大类疫情服务紧缺 阿里广发英雄帖抗疫小程序开发者最高可获50万元奖励
  6. 关于肉鸡的一些使用教程
  7. 数据结构中三表合一的实现
  8. git修改本地和远程仓库名称的解决方法
  9. C#实现动态桌面背景图片切换(续)
  10. Java 二十五载,正在 Kotlin 化!
  11. Unity3D游戏开发之邂逅Unity3D
  12. 数组元素在删减的同时进行遍历的操作,程序崩溃问题
  13. python 代理服务器 身份验证_使用httplib2处理身份验证和代理服务器
  14. JAVA基础-XML的解析
  15. SVN仓库解决APIcloud2检出错误
  16. Java-JVM调优经验
  17. 网络测量工具及其使用
  18. magic API构建和基础实现
  19. java 拼音排序:Collator类
  20. Jersey框架一:Jersey RESTful WebService框架简介

热门文章

  1. syslog简介——系统日志写入API
  2. 算法 - python - 判断链表是否有环
  3. 【c++基础】ifstream的构造函数
  4. CentOS系统上编译、安装、配置OpenCV
  5. centos下如何停止ping命令
  6. hibernate中的锁
  7. 在C#后端处理一些结果然传给前端Javascript或是jQuery
  8. Linux IP怎么设置
  9. 0,1,2,3,2,1,0,1,2,3,2,1,0,...
  10. Linux gsoap 访问Jira