导读:?说到php,一句顺口溜流传已广:php是世界上最好的语言;还有一个特别的谐音名字:拍xx片。至于php是不是世界上最好的语言,这个有意思的口号我们也探究一下他的来源。
更多优质内容请
2.类加载:通过ClassLoader及其子类来完成JVM的类加载
3.类执行:字节码被装入内存,进入JVM虚拟机,被解释器解释执行
?
注:Java平台由Java虚拟机和Java应用程序接口搭建,Java语言则是进入这个平台的通道,
??用Java语言编写并编译的程序可以运行在这个平台上
1.java程序经过一次编译之后,将java代码编译为字节码也就是class文件,然后在不同的操作系统上依靠不同的java虚拟机进行解释,最后再转换为不同平台的机器码,最终得到执行
2.Java虚拟机(JVM)处在核心的位置,是程序与底层操作系统、硬件无关的关键。
JVM的下方是移植接口,移植接口由两部分组成:适配器和Java操作系统,其中依赖于平台的部分称为适配器,JVM通过移植接口在具体的平台和操作系统上实现
JVM的上方是Java的基本类库和扩展类库以及它们的API,利用JavaAPI编写的应用程序(application)和小程序(Javaapplet)可以在任何Java平台上运行而无需考虑底层平台
Java虚拟机(JVM)实现了程序与操作系统的分离,从而实现了Java的跨平台
????
3.JVM在它的生存周期中有一个明确的任务,那就是运行Java程序,因此当Java程序启动的时候,就产生JVM的一个实例;当程序运行结束的时候,该实例也跟着消失了
.三种JVM:①Sun公司的HotSpot?②BEA公司的JRockit?③IBM公司的J9JVM
在JDK1.7及其以前我们所使用的都是Sun公司的HotSpot,但由于Sun公司和BEA公司都被oracle收购,jdk1.8将采用Sun公司的HotSpot和BEA公司的JRockit两个JVM中精华形成jdk1.8的JVM。
三、JVM体系结构
1.ClassLoader类加载器
?????负责加载.class文件,class文件在文件开头有特定的文件标示,并且ClassLoader负责class文件的加载等,至于它是否可以运行,则由ExecutionEngine决定。
①定位和导入二进制class文件
②验证导入类的正确性
③为类分配初始化内存
④帮助解析符号引用.
2.NativeInterface本地接口
本地接口的作用是融合不同的编程语言为Java所用,它的初衷是融合C/C++程序,Java诞生的时候C/C++横行的时候,要想立足,必须有调用C/C++程序,于是就在内存中专门开辟了一块区域处理标记为
native的代码,它的具体作法是NativeMethodStack中登记native方法,在ExecutionEngine执行时加载nativelibraies。
目前该方法使用的越来越少了,除非是与硬件有关的应用,比如通过Java程序驱动打印机,或者Java系统管理生产设备,在企业级应用中已经比较少见。
因为现在的异构领域间的通信很发达,比如可以使用Socket通信,也可以使用WebService等。
3.ExecutionEngine执行引擎:执行包在装载类的方法中的指令,也就是方法。
.Runtimedataarea运行数据区(即:虚拟机内存或者JVM内存下节介绍)
????从整个计算机内存中开辟一块内存存储Jvm需要用到的对象,变量等,分为:方法区,堆,虚拟机栈,程序计数器,本地方法栈。
四、JVM内存结构?1.程序计数器PCRegister
每个线程都有一个程序计算器,就是一个指针,指向方法区中的方法字节码(下一个将要执行的指令代码),由执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不记。
程序计数器(ProgramCounterRegister)是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的方式去实现),字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Natvie方法,这个计数器值则为空(Undefined)。此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
2.本地方法栈?NativeMethodStack
NativeMethodStack中登记native方法,在ExecutionEngine执行时加载nativelibraies
本地方法栈与虚拟机栈基本类似,区别在于虚拟机栈为虚拟机执行的java方法服务,而本地方法栈则是为Native方法服务
3.方法区??MethodArea
用于存储虚拟机加载的:静态变量+常量+类信息+运行时常量池?(类信息:类的版本、字段、方法、接口、构造函数等描述信息)
默认最小值为16MB,最大值为6MB,可以通过-XX:PermSize?和?-XX:MaxPermSize?参数限制方法区的大小
对于习惯在HotSpot虚拟机上开发和部署程序的开发者来说,很多人愿意把方法区称为“永久代”(PermanentGeneration),本质上两者并不等价,仅仅是因为HotSpot虚拟机的设计团队选择把GC分代收集扩展至方法区,或者说使用永久代来实现方法区而已。对于其他虚拟机(如BEAJRockit、IBMJ9等)来说是不存在永久代的概念的。即使是HotSpot虚拟机本身,根据官方发布的路线图信息,现在也有放弃永久代并“搬家”至NativeMemory来实现方法区的规划了。Java虚拟机规范对这个区域的限制非常宽松,除了和Java堆一样不需要连续的内存和可以选择固定大小或者可扩展外,还可以选择不实现垃圾收集。相对而言,垃圾收集行为在这个区域是比较少出现的,但并非数据进入了方法区就如永久代的名字一样“永久”存在了。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载,一般来说这个区域的回收“成绩”比较难以令人满意,尤其是类型的卸载,条件相当苛刻,但是这部分区域的回收确实是有必要的。在Sun公司的BUG列表中,曾出现过的若干个严重的BUG就是由于低版本的HotSpot虚拟机对此区域未完全回收而导致内存泄漏。根据Java虚拟机规范的规定,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。
.栈?JVMStack
编译器可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(引用指针,并非对象本身)
栈是java方法执行的内存模型:
每个方法被执行的时候都会创建一个“栈帧”用于存储局部变量表(包括参数)、操作栈、方法出口等信息。
每个方法被调用到执行完的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
(局部变量表:存放了编译器可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(引用指针,并非对象本身),
其中6位长度的long和double类型的数据会占用2个局部变量的空间,其余数据类型只占1个。
局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量是完全确定的,在运行期间栈帧不会改变局部变量表的大小空间)
栈的生命期是跟随线程的生命期,线程创建时创建,线程结束栈内存也就释放,是线程私有的。
5.堆??JavaHeap
所有的对象实例以及数组都要在堆上分配,此内存区域的唯一目的就是存放对象实例
堆是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建
堆是理解JavaGC机制最重要的区域,没有之一
结构:新生代(Eden区+2个Survivor区)?老年代??永久代(HotSpot有)
新生代:新创建的对象——Eden区?
GC之后,存活的对象由Eden区?Survivor区0进入Survivor区1??
再次GC,存活的对象由Eden区?Survivor区1进入Survivor区0?
老年代:对象如果在新生代存活了足够长的时间而没有被清理掉(即在几次YoungGC后存活了下来),则会被复制到老年代
如果新创建对象比较大(比如长字符串或大数组),新生代空间不足,则大对象会直接分配到老年代上(大对象可能触发提前GC,应少用,更应避免使用短命的大对象)
老年代的空间一般比新生代大,能存放更多的对象,在老年代上发生的GC次数也比年轻代少
永久代:可以简单理解为方法区(本质上两者并不等价)
如上文所说:对于习惯在HotSpot虚拟机上开发和部署程序的开发者来说,很多人愿意把方法区称为“永久代”,本质上两者并不等价
仅仅是因为HotSpot虚拟机的设计团队选择把GC分代收集扩展至方法区,或者说使用永久代来实现方法区而已
对于其他虚拟机(如BEAJRockit、IBMJ9等)来说是不存在永久代的概念的
即使是HotSpot虚拟机本身,根据官方发布的路线图信息,现在也有放弃永久代并“搬家”至NativeMemory来实现方法区的规划了
Jdk1.6及之前:常量池分配在永久代
Jdk1.7:有,但已经逐步“去永久代”
Jdk1.8及之后:没有永久代(java.lang.OutOfMemoryError:PermGenspace,这种错误将不会出现在JDK1.8中)
6.直接内存?DirectMemor
直接内存并不是JVM管理的内存,可以这样理解,直接内存,就是JVM以外的机器内存,比如,你有G的内存,JVM占用了1G,则其余的3G就是直接内存
JDK中有一种基于通道(Channel)和缓冲区(Buffer)的内存分配方式,将由C语言实现的native函数库分配在直接内存中,用存储在JVM堆中的DirectByteBuffer来引用
由于直接内存收到本机器内存的限制,所以也可能出现OutOfMemoryError的异常。
总结:
我们可以发现:
1:无论是java还是php,虚拟机干的活都差不多,编译成中间码,负责中间码的执行,执行过程中内存管理
2:虚拟机本身就是一个系统,专门负责这门语言管理的操作系统,并且留个接口给外面对接
3:至于java和php不同的数据结构,不同的中间码等等这些就稍微有些区别,但最终都落脚到cpu去执行机器码,哪个中间码离机器码越近,那么执行效率越高
03?php与java对比1、php与Java的语法比较
1)、注释
java支持:双斜杠(//)、/**/;PHP支持:双斜杠(//)、#符号、/**/。
2)、大小写敏感
在java中,所有函数名,关键字,类,变量等都是大小写敏感的;在PHP中,变量是大小写敏感的,而用户自定义的函数、类和关键字对大小写不敏感。
php是解释执行的服务器脚本语言,首先php有简单容易上手的特点。语法和c语言比较象,所以学过c语言的程序员可以很快的熟悉php的开发。
java的学习需要先学好java的语法和熟悉一些核心的类库,java处处面向对象,学java懂得面向对象的程序设计方法,所以java不如php好学。
更加直观一些的表达:php的语法和使用更加容易,java更多用类库和包来支撑生态
2、php与Java系统架构设计的对比
如果非得说到系统架构,php和java本质上区别不大,主要架构都是从域名解析负载均衡到代码服务器到缓存最后到数据库,最后的主要瓶颈都在数据库这层,而数据库通过缓存,集群,异步的方式都能很好的解决架构问题,这里我们可以看到系统架构上和语言有一定关系,但是主要因素还不在语言这一个层面。
一些常用的数据php可以通过nginxmodule直达缓存(memached与redis),失效后调用代码刷新,有的时候都还不需要经过语言这一层,这就是架构的魅力,但是落到细节的java和php语言成面的东西还是有一些区别,比如并发,长链接的处理。
实在要追求运行效率,php的c扩展足以解决,所以php大并发架构不如java的说法是不完全正确的,java能支持的大并发架构,php也是可以实现的;架构好不好,和语言有一定关系,更多的是在于使用这门语言的人。
3、php与Java访问数据库速度的比较
php对于不同的数据库采用不同的数据库访问接口,所以数据库访问代码的通用性不强。例如:用Java开发的Web应用从MySQL数据库转到Oracle数据库只需要做很少的修改。而php则需要做大量的修改工作。
Java通过JDBC来访问数据库,通过不同的数据库厂商提供的数据库驱动方便地访问数据库。访问数据库的接口比较统一。
、php与Java源代码安全的对比
PHP开发的程序的源代码一般是公开的,也可以通过zend加密,至于安全性,通过sql注入拦截,外界传入数据拦截再加上linux服务器安全,自然也是安全的。
Java开发的程序,最后用户拿到的是只是一些编译好的class类,安全性是有一定提高。
5、php与Java开发成本的对比
PHP最经典的组合就是:PHP+MySQL+nginx+linux。非常适合开发中小型的Web应用,开发的速度比较快。而且所有的软件都是开源免费的,可以减少投入。
Java的Web应用服务器有免费Tomcat、JBoss等,如果需要更好的商业化的服务有:WebSphere和Weblogic。
6、php与Java的性能比较
php7的性能已经有很大提高,某些情况下与java性能相当,但是由于java是编译型语言,变量常驻内存以及多线程,java在性能上还是有不错的表现
7:我该学php还是java
php简单易学,容易上手,java生态丰富,在大数据上优势明显,php做到一定程度只在web范围内,不便于长远发展,所以做php的同学可以做到一定程度同时开始java和go的学习
8:我们公司技术选型用java还是go
看公司目前的业务状态,如果是web,用java和go都一样,而在于你的技术leader对java还是go更熟悉,也在于你所在城市哪个语言的市场供应比较多
9:为什么市场上的php越来越少
这是一个很值得思考的问题,至从微服务出来以后,springboot,springcloud把web开发占据了很大一部分江山,而整个互联网进入更加深层次的存量竞争,原来简单的web系统已经不满足业务需求;同时更在于php和java两个语言从业人员的本身基础问题,因为php相对上手容易,所以市场上有大量基础一般的人存在,导致业务系统常常有一些状况,而java要能跑起来对基础还是有一定要求,结果就造成了好像java系统越来越坚固的假象,实质上语言上是差别不大,而是两种语言的从业人员的素质有一定差别。
php与其php与其他语言还有一些对比和差别,这里小编就不一一展开了,以后再详细展开
结论思考回到最开始的问题,php是不是世界上最好的语言,我们一起来揭开这个谜底,相信看完上面的文字心里应该有一定数了
1:从语言本身设计或者出发点来讲php要说是世界上最好的语言,可能并不会很夸张,只是其应用场景更多的局限与web
2:至于"php是世界上最好的语言"这个段子什么时候开始流传的,我也不能追溯到,只是想到一种可能场景:在一个团队内,有java也有php,突然某天java能解决的问题php没解决了,主管要把php转java,而php是不服的,大声表达:php是世界上最好的语言
或许,php是世界上最好的语言是基于以上两个因素同时而产生的,至于php是不是世界上的语言并不重要,各自有各自的场景,而"php是世界上最好的语言"这个段子就让他继续流传吧,这是程序猿界少有的段子,是我们happy的源泉,也或许是很多人骄傲的源泉,开心很重要
写一篇不错的文章需要花很多的时间,更重要的是这些更加接近真相的东西我们需要让更多的人知道,是对社会,是更多人共多的贡献,只有大家都有钱了,我们自己也才能让他们身上赚到更多的钱
觉得不错就帮小编点赞和转发吧。
肉眼品世界?
发现世界之美好(ID:find_world_fine),独立理性之观点,从技术架构,到研发管理再到商业视觉再到创业人生的升级之路,深厚的技术、研发管理体系价值观与互联网商业分析输出,助力每个个人与企业高速发展。愿景:通过共赢的方式推动社会知识创新,释放社会创新活力
文章已于修改