1991年4月,由James Gosling主导的团队创造了Oak语言,java的前身,1995年5月23号,Oak语言改名Java,而且提出那句注明的:”write Once,Run Anywhere”的口号.1996年1月23日,JDK1.0发布.前端
当时正好遇上浏览器快速崛起,发展的浪潮,你们发现java一处编译处处使用的特性和浏览器很契合,同一个页面不可能每个操做系统我都写一遍.用如今的话说java正好站在这个风口上.致使它飞速发展才有了今天的江湖地位.java
JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是经过在实际的计算机上仿真模拟各类计算机功能来实现的。Java虚拟机包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。 JVM屏蔽了与具体操做系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就能够在多种平台上不加修改地运行。JVM在执行字节码时,实际上最终仍是把字节码解释成具体平台上的机器指令执行。程序员
Java语言的一个很是重要的特色就是与平台的无关性。而使用Java虚拟机是实现这一特色的关键。通常的高级语言若是要在不一样的平台上运行,至少须要编译成不一样的目标代码。而引入Java语言虚拟机后,Java语言在不一样平台上运行时不须要从新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就能够在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是Java的可以“一次编译,处处运行”的缘由。面试
咱们先把JVM这个虚拟机画出来,以下图所示:算法
从这张图中咱们能够看出,JVM是运行在操做系统之上的,它与硬件没有直接的交互,咱们再来看JVM由哪些部分组成,以下图所示:编程
一、Class Loader 类加载器浏览器
类加载器的做用是加载类文件到内存,好比编写一个HelloWord.java 程序,而后经过javac 编译成class 文件,那怎么才能加载到内存中被执行呢?Class Loader 承担的就是这个责任,那不可能随便创建一个.class 文件就能被加载的,Class Loader 加载的class 文件是有格式要求。缓存
Class Loader 只管加载,只要符合文件结构就加载,至于说能不能运行,则不是它负责的,那是由Execution Engine 负责的。安全
二、Execution Engine 执行引擎性能优化
执行引擎也叫作解释器(Interpreter) ,负责解释命令,提交操做系统执行。
三、Native Interface 本地接口
本地接口的做用是融合不一样的编程语言为Java 所用,它的初衷是融合C/C++ 程序,Java 诞生的时候是C/C++ 横行的时候,要想立足,必须有一个聪明的、睿智的调用C/C++ 程序,因而就在内存中专门开辟了一块区域处理标记为native 的代码,它的具体作法是Native Method Stack 中登记native 方法,在Execution Engine 执行时加载native libraies 。目前该方法使用的是愈来愈少了,除非是与硬件有关的应用,好比经过Java 程序驱动打印机,或者Java 系统管理生产设备,在企业级应用中已经比较少见,由于如今的异构领域间的通讯很发达,好比可使用Socket 通讯,也可使用Web Service 等等,很少作介绍。
四、 Runtime data area 运行数据区
运行数据区是整个JVM 的重点。咱们全部写的程序都被加载到这里,以后才开始运行,Java 生态系统如此的繁荣,得益于该区域的优良自治。
整个JVM 框架由加载器加载文件,而后执行器在内存中处理数据,须要与异构系统交互是能够经过本地接口进行,瞧,一个完整的系统诞生了!
全部的数据和程序都是在运行数据区存放,它包括如下几部分:
一、 Stack 栈
栈也叫栈内存,是Java程序的运行区,是在线程建立时建立,它的生命期是跟随线程的生命期,线程结束栈内存也就释放,对于栈来讲不存在垃圾回收问题,只要线程一结束,该栈就Over。问题出来了:栈中存的是那些数据呢?又什么是格式呢?
栈中的数据都是以栈帧(Stack Frame)的格式存在,栈帧是一个内存区块,是一个数据集,是一个有关方法(Method)和运行期数据的数据集,当一个方法A被调用时就产生了一个栈帧F1,并被压入到栈中,A方法又调用了B方法,因而产生栈帧F2也被压入栈,执行完毕后,先弹出F2栈帧,再弹出F1栈帧,遵循“先进后出”原则。
那栈帧中到底存在着什么数据呢?栈帧中主要保存3类数据:本地变量(Local Variables),包括输入参数和输出参数以及方法内的变量;栈操做(Operand Stack),记录出栈、入栈的操做;栈帧数据(Frame Data),包括类文件、方法等等。光说比较枯燥,咱们画个图来理解一下Java栈,以下图所示:
示在一个栈中有两个栈帧,栈帧2是最早被调用的方法,先入栈,而后方法2又调用了方法1,栈帧1处于栈顶的位置,栈帧2处于栈底,执行完毕后,依次弹出栈帧1和栈帧2,线程结束,栈释放。
二、Heap 堆内存
jvm中分为堆和方法区,**堆**又进一步分为**新生代和老年代,方法区为永久代。**
堆中区分的新生代和老年代是为了垃圾回收,新生代中的对象存活期通常不长,而老年代中的对象存活期较长,因此当垃圾回收器回收内存时,新生代中垃圾回收效果较好,会回收大量的内存,而老年代中回收效果较差,内存回收不会太多。
基于以上特性,新生代中通常采用复制算法,由于存活下来的对象是少数,所须要复制的对象少,而老年代对象存活多,不适合采用复制算法,通常是标记整理和标记清除算法。
由于复制算法须要留出一块单独的内存空间来以备垃圾回收时复制对象使用,因此将新生代分为eden区和两个survivor区,每次使用eden和一个survivor区,另外一个survivor做为备用的对象复制内存区。
一个JVM实例只存在一个堆类存,堆内存的大小是能够调节的。类加载器读取了类文件后,须要把类、方法、常变量放到堆内存中,以方便执行器执行,堆内存分为三部分:
Permanent Space 永久存储区
永久存储区是一个常驻内存区域,用于存放JDK自身所携带的Class,Interface的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,关闭JVM才会释放此区域所占用的内存。
Young Generation Space 新生区
新生区是类的诞生、成长、消亡的区域,一个类在这里产生,应用,最后被垃圾回收器收集,结束生命。新生区又分为两部分:伊甸区(Eden space)和幸存者区(Survivor pace),全部的类都是在伊甸区被new出来的。幸存区有两个: 0区(Survivor 0 space)和1区(Survivor 1 space)。当伊甸园的空间用完时,程序又须要建立对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收,将伊甸园区中的再也不被其余对象所引用的对象进行销毁。而后将伊甸园中的剩余对象移动到幸存0区。若幸存0区也满了,再对该区进行垃圾回收,而后移动到1区。那若是1区也满了呢?再移动到养老区。
Tenure generation space养老区
养老区用于保存重新生区筛选出来的JAVA对象,通常池对象都在这个区域活跃。 三个区的示意图以下:
三、 Method Area 方法区
方法区是被全部线程共享,该区域保存全部字段和方法字节码,以及一些特殊方法如构造函数,接口代码也在此定义。
四、PC Register 程序计数器
每一个线程都有一个程序计数器,就是一个指针,指向方法区中的方法字节码,由执行引擎读取下一条指令。
GC (Garbage Collection)的基本原理:将内存中再也不被使用的对象进行回收,GC中用于回收的方法称为收集器,因为GC须要消耗一些资源和时间,Java在对对象的生命周期特征进行分析后,按照新生代、旧生代的方式来对对象进行收集,以尽量的缩短GC对应用形成的暂停
(1)对新生代的对象的收集称为minor GC;
(2)对旧生代的对象的收集称为Full GC;
(3)程序中主动调用System.gc()强制执行的GC为Full GC。
不一样的对象引用类型, GC会采用不一样的方法进行回收,JVM对象的引用分为了四种类型:
(1)强引用:默认状况下,对象采用的均为强引用(这个对象的实例没有其余对象引用,GC时才会被回收)
(2)软引用:软引用是Java中提供的一种比较适合于缓存场景的应用(只有在内存不够用的状况下才会被GC)
(3)弱引用:在GC时必定会被GC回收
(4)虚引用:因为虚引用只是用来得知对象是否被GC
4、JVM的发展
1.Sun Classic / Exact VM
以今天的视角来看,Sun Classic VM的技术可能很原始,这款虚拟机的使命也早已终结。但仅凭它“世界上第一款商用Java虚拟机”的头衔,就足够有让历史记住它的理由。
1996年1月23日,Sun公司发布JDK 1.0,Java语言首次拥有了商用的正式运行环境,这个JDK中所带的虚拟机就是Classic VM。这款虚拟机只能使用纯解释器方式来执行Java代码,若是要使用JIT编译器,就必须进行外挂。可是假如外挂了JIT编译器,JIT编译器就彻底接管了虚拟机的执行系统,解释器便再也不工做了。用户在这款虚拟机上执行java -version命令,将会看到相似下面这行输出:
1. java version "1.2.2"
2. Classic VM (build JDK-1.2.2-001, green threads, sunwjit)
Sun的虚拟机团队努力去解决Classic VM所面临的各类问题,提高运行效率。在JDK 1.2时,曾在Solaris平台上发布过一款名为Exact VM的虚拟机,它的执行系统已经具有现代高性能虚拟机的雏形:如两级即时编译器、编译器与解释器混合工做模式等。Exact VM因它使用准确式内存管理(Exact Memory Management,也能够叫Non-Conservative/Accurate Memory Management)而得名,即虚拟机能够知道内存中某个位置的数据具体是什么类型。虽然Exact VM的技术相对Classic VM来讲先进了许多,可是在商业应用上只存在了很短暂的时间就被更为优秀的HotSpot VM所取代,甚至尚未来得及发布Windows和Linux平台下的商用版本。而Classic VM的生命周期则相对长了许多,它在JDK 1.2以前是Sun JDK中惟一的虚拟机,在JDK 1.2时,它与HotSpot VM并存,但默认使用的是Classic VM(用户可用java-hotspot参数切换至HotSpot VM),而在JDK 1.3时,HotSpot VM成为默认虚拟机,但Classic VM仍做为虚拟机的“备用选择”发布(使用java-classic参数切换),直到JDK 1.4的时候,Classic VM才彻底退出商用虚拟机的历史舞台,与Exact VM一块儿进入了Sun Labs Research VM之中。
2.Sun HotSpot VM**
提起HotSpot VM,相信全部Java程序员都知道,它是Sun JDK和OpenJDK中所带的虚拟机,也是目前使用范围最广的Java虚拟机。但不必定全部人都知道的是,这个目前看起来“血统纯正”的虚拟机在最初并不是由Sun公司开发,而是由一家名为“Longview Technologies”的小公司设计的;甚至这个虚拟机最初并不是是为Java语言而开发的,它来源于Strongtalk VM,而这款虚拟机中至关多的技术又是来源于一款支持Self语言实现“达到C语言50%以上的执行效率”的目标而设计的虚拟机,Sun公司注意到了这款虚拟机在JIT编译上有许多优秀的理念和实际效果,在1997年收购了Longview Technologies公司,从而得到了HotSpot VM。
HotSpot VM既继承了Sun以前两款商用虚拟机的优势,也有许多本身新的技术优点,如它名称中的HotSpot指的就是它的热点代码探测技术,HotSpot VM的热点代码探测能力能够经过执行计数器找出最具备编译价值的代码,而后通知JIT编译器以方法为单位进行编译。若是一个方法被频繁调用,或方法中有效循环次数不少,将会分别触发标准编译和OSR(栈上替换)编译动做。经过编译器与解释器恰当地协同工做,能够在最优化的程序响应时间与最佳执行性能中取得平衡,并且无须等待本地代码输出才能执行程序,即时编译的时间压力也相对减少,这样有助于引入更多的代码优化技术,输出质量更高的本地代码。
在2006年的JavaOne大会上,Sun公司宣布最终会把Java开源,并在随后的一年,陆续将JDK的各个部分(其中固然也包括了HotSpot VM)在GPL协议下公开了源码,并在此基础上创建了OpenJDK。这样,HotSpot VM便成为了Sun JDK和OpenJDK两个实现极度接近的JDK项目的共同虚拟机。
在2008年和2009年,Oracle公司分别收购了BEA公司和Sun公司,这样Oracle就同时拥有了两款优秀的Java虚拟机:JRockit VM和HotSpot VM。Oracle公司宣布在不久的未来(大约应在发布JDK 8的时候)会完成这两款虚拟机的整合工做,使之优点互补。整合的方式大体上是在HotSpot的基础上,移植JRockit的优秀特性,譬如使用JRockit的垃圾回收器与MissionControl服务,使用HotSpot的JIT编译器与混合的运行时系统。
3. Sun Mobile-Embedded VM / Meta-Circular VM
Sun公司所研发的虚拟机可不只有前面介绍的服务器、桌面领域的商用虚拟机,除此以外,Sun公司面对移动和嵌入式市场,也发布过虚拟机产品,另外还有一类虚拟机,在设计之初就没抱有商用的目的,仅仅是用于研究、验证某种技术和观点,又或者是做为一些规范的标准实现。这些虚拟机对于大部分不从事相关领域开发的Java程序员来讲可能比较陌生。Sun公司发布的其余Java虚拟机有:
(1)KVM
KVM中的K是“Kilobyte”的意思,它强调简单、轻量、高度可移植,可是运行速度比较慢。在Android、iOS等智能手机操做系统出现前曾经在手机平台上获得很是普遍的应用。
(2)CDC/CLDC HotSpot Implementation
CDC/CLDC全称是Connected(Limited)Device Configuration,在JSR-139/JSR-218规范中进行定义,它但愿在手机、电子书、PDA等设备上创建统一的Java编程接口,而CDC-HI VM和CLDC-HI VM则是它们的一组参考实现。CDC/CLDC是整个Java ME的重要支柱,但从目前Android和iOS二分天下的移动数字设备市场看来,在这个领域中,Sun的虚拟机所面临的局面远不如服务器和桌面领域乐观。
(3)Squawk VM
Squawk VM由Sun公司开发,运行于Sun SPOT(Sun Small Programmable Object Technology,一种手持的WiFi设备),也曾经运用于Java Card。这是一个Java代码比重很高的嵌入式虚拟机实现,其中诸如类加载器、字节码验证器、垃圾收集器、解释器、编译器和线程调度都是Java语言自己完成的,仅仅靠C语言来编写设备I/O和必要的本地代码。
(4)JavaInJava
JavaInJava是Sun公司于1997年~1998年间研发的一个实验室性质的虚拟机,从名字就能够看出,它试图以Java语言来实现Java语言自己的运行环境,既所谓的“元循环”(Meta-Circular,是指使用语言自身来实现其运行环境)。它必须运行在另一个宿主虚拟机之上,内部没有JIT编译器,代码只能以解释模式执行。在20世纪末主流Java虚拟机都未能很好解决性能问题的时代,开发这种项目,其执行速度可想而知。
(5)Maxine VM
Maxine VM和上面的JavaInJava很是类似,它也是一个几乎所有以Java代码实现(只有用于启动JVM的加载器使用C语言编写)的元循环Java虚拟机。这个项目于2005年开始,到如今仍然在发展之中,比起JavaInJava,Maxine VM就显得“靠谱”不少,它有先进的JIT编译器和垃圾收集器(但没有解释器),可在宿主模式或独立模式下执行,其执行效率已经接近了HotSpot Client VM的水平。
4. BEA JRockit / IBM J9 VM
Oracle JRockit (原来的 Bea JRockit)系列产品是一个全面的[Java](https://baike.baidu.com/item/Java/85979)运行时解决方案组合,包括了行业最快的标准Java解决方案。 大量的行业[基准测试](https://baike.baidu.com/item/%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95/5876292)显示,基本JRockit JVM是世界上最快的[JVM](https://baike.baidu.com/item/JVM/2902369)。JRockit面向延迟敏感型应用的解决方案JRockit Real Time提供以毫秒或微秒级的JVM响应时间,适合财务前端办公、军事指挥与控制和电信网络的须要。使用JRockit产品,客户已经体验到了显著的性能提升(一些超过了70% )和硬件成本的减小(达50%)。
JRockit VM曾经号称“世界上速度最快的Java虚拟机”它是BEA公司在2002年从Appeal Virtual Machines公司收购的虚拟机。BEA公司将其发展为一款专门为服务器硬件和服务器端应用场景高度优化的虚拟机,因为专一于服务器端应用,它能够不太关注程序启动速度,所以JRockit内部不包含解析器实现,所有代码都靠即时编译器编译后执行。除此以外,JRockit的垃圾收集器和MissionControl服务套件等部分的实现,在众多Java虚拟机中也一直处于领先水平。
IBM J9 VM并非IBM公司惟一的Java虚拟机,不过是目前其主力发展的Java虚拟机。IBM J9 VM本来是内部开发代号,正式名称是“IBM Technology for Java Virtual Machine”,简称IT4J,只是这个名字太拗口了一点,普及程度不如J9。J9 VM最初是由IBM Ottawa实验室一个名为SmallTalk的虚拟机扩展而来的,当时这个虚拟机有一个bug是由8k值定义错误引发的,工程师花了很长时间终于发现并解决了这个错误,此后这个版本的虚拟机就称为K8了,后来扩展出支持Java的虚拟机就被称为J9了。与BEA JRockit专一于服务器端应用不一样,IBM J9的市场定位与Sun HotSpot比较接近,它是一款设计上从服务器端到桌面应用再到嵌入式都全面考虑的多用途虚拟机,J9的开发目的是做为IBM公司各类Java产品的执行平台,它的主要市场是和IBM产品(如IBM WebSphere等)搭配以及在IBM AIX和z/OS这些平台上部署Java应用。
5. Azul VM / BEA Liquid VM
咱们平时所说起的“高性能Java虚拟机”通常是指HotSpot、JRockit、J9这类在通用平台上运行的商用虚拟机,但其实Azul VM和BEA Liquid VM这类特定硬件平台专有的虚拟机才是“高性能”的武器。
Azul VM是Azul Systems 公司在HotSpot基础上进行大量改进,运行于Azul Systems公司的专有硬件Vega系统上的Java虚拟机,每一个Azul VM实例均可以管理至少数十个CPU和数百GB内存的硬件资源,并提供在巨大内存范围内实现可控的GC时间的垃圾收集器、为专有硬件优化的线程调度等优秀特性。在2010年,Azul Systems公司开始从硬件转向软件,发布了本身的Zing JVM,能够在通用x86平台上提供接近于Vega系统的特性。
Liquid VM便是如今的JRockit VE(Virtual Edition),它是BEA公司开发的,能够直接运行在自家Hypervisor系统上的JRockit VM的虚拟化版本,Liquid VM不须要操做系统的支持,或者说它本身自己实现了一个专用操做系统的必要功能,如文件系统、网络支持等。由虚拟机越过通用操做系统直接控制硬件能够得到不少好处,如在线程调度时,不须要再进行内核态/用户态的切换等,这样能够最大限度地发挥硬件的能力,提高Java程序的执行性能。
6. Apache Harmony / Google Android Dalvik VM
Harmony VM和Dalvik VM只能称作“虚拟机”,而不能称作“Java虚拟机”,可是这两款虚拟机(以及所表明的技术体系)对最近几年的Java世界产生了很是大的影响和挑战,甚至有些悲观的评论家认为成熟的Java生态系统有崩溃的可能。
Apache Harmony是一个Apache软件基金会旗下以Apache License协议开源的实际兼容于JDK 1.5和JDK 1.6的Java程序运行平台,这个介绍至关拗口。它包含本身的虚拟机和Java库,用户能够在上面运行Eclipse、Tomcat、Maven等常见的Java程序,可是它没有经过TCK认证,因此咱们不得不用那么一长串拗口的语言来介绍它,而不能用一句“Apache的JDK”来讲明。若是一个公司要宣布本身的运行平台“兼容于Java语言”,那就必需要经过TCK(Technology Compatibility Kit)的兼容性测试。Apache基金会曾要求Sun公司提供TCK的使用受权,可是一直遭到拒绝,直到Oracle公司收购了Sun公司以后,双方关系越闹越僵,最终致使Apache愤然退出JCP(Java Community Process)组织,这是目前为止Java社区最严重的一次“分裂”。
在Sun将JDK开源造成OpenJDK以后,Apache Harmony开源的优点被极大地削弱,甚至连Harmony项目的最大参与者IBM公司也宣布辞去Harmony项目管理主席的职位,并参与OpenJDK项目的开发。虽然Harmony没有通过真正大规模的商业运用,可是它的许多代码(基本上是Java库部分的代码)被吸纳进IBM的JDK 7实现及Google Android SDK之中,尤为是对Android的发展起到了很大的推进做用。
说到Android,这个时下最热门的移动数码设备平台在最近几年间的发展过程当中所取得的成果已经远远超越了Java ME在过去十多年所得到的成果,Android让Java语言真正走进了移动数码设备领域,只是走的并不是Sun公司本来想象的那一条路。
Dalvik VM是Android平台的核心组成部分之一,它的名字来源于冰岛一个名为Dalvik的小渔村。Dalvik VM并非一个Java虚拟机,它没有遵循Java虚拟机规范,不能直接执行Java的Class文件,使用的是寄存器架构而不是JVM中常见的栈架构。可是它与Java又有着千丝万缕的联系,它执行的dex(Dalvik Executable)文件能够经过Class文件转化而来,使用Java语法编写应用程序,能够直接使用大部分的Java API等。目前Dalvik VM随着Android一块儿处于迅猛发展阶段,在Android 2.2中已提供即时编译器实现,在执行性能上有了很大的提升。
7. Microsoft JVM及其余
在十几年的Java虚拟机发展过程当中,除去上面介绍的那些被大规模商业应用过的Java虚拟机外,还有许多虚拟机是鲜为人知的或者曾经“绚丽”过但最终湮灭的。咱们以其中微软公司的JVM为例来介绍一下。
也许Java程序员听起来可能会以为惊讶,微软公司曾经是Java技术的铁杆支持者(也必须认可,与Sun公司争夺Java的控制权,令Java从跨平台技术变为绑定在Windows上的技术是微软公司的主要目的)。在Java语言诞生的初期(1996年~1998年,以JDK 1.2发布为分界),它的主要应用之一是在浏览器中运行Java Applets程序,微软公司为了在IE3中支持Java Applets应用而开发了本身的Java虚拟机,虽然这款虚拟机只有Windows平台的版本,倒是当时Windows下性能最好的Java虚拟机,它在1997年和1998年连续两年得到了《PC Magazine》杂志的“编辑选择奖”。但好景不长,在1997年10月,Sun公司正式以侵犯商标、不正当竞争等罪名控告微软公司,在随后对微软公司的垄断调查之中,这款虚拟机也曾做为证据之一被呈送法庭。这场官司的结果是微软公司赔偿2000万美金给Sun公司(最终微软公司因垄断赔偿给Sun公司的总金额高达10亿美圆),承诺终止其Java虚拟机的发展,并逐步在产品中移除Java虚拟机相关功能。具备讽刺意味的是,到最后在Windows XP SP3中Java虚拟机被彻底抹去的时候,Sun公司却又处处登报但愿微软公司不要这样作。Windows XP高级产品经理Jim Cullinan称:“咱们花费了3年的时间和Sun打官司,当时他们试图阻止咱们在Windows中支持Java,如今咱们这样作了,可他们又在抱怨,这太具备讽刺意味了。”
咱们试想一下,若是当年Sun公司没有起诉微软公司,微软公司继续保持着对Java技术的热情,那Java的世界会变得怎么样呢?.NET技术是否会发展起来?但历史是没有假设的。
问:堆和栈有什么区别
答:堆是存放对象的,可是对象内的临时变量是存在栈内存中,如例子中的methodVar是在运行期存放到栈中的。
栈是跟随线程的,有线程就有栈,堆是跟随JVM的,有JVM就有堆内存。
问:堆内存中到底存在着什么东西?
答:对象,包括对象变量以及对象方法。
问:类变量和实例变量有什么区别?
答:静态变量是类变量,非静态变量是实例变量,直白的说,有static修饰的变量是静态变量,没有static修饰的变量是实例变量。静态变量存在方法区中,实例变量存在堆内存中。
问:我据说类变量是在JVM启动时就初始化好的,和你这说的不一样呀!
答:那你是道听途说,信个人,没错。
问:Java的方法(函数)究竟是传值仍是传址?
答:都不是,是以传值的方式传递地址,具体的说原生数据类型传递的值,引用类型传递的地址。对于原始数据类型,JVM的处理方法是从Method Area或Heap中拷贝到Stack,而后运行frame中的方法,运行完毕后再把变量指拷贝回去。
问:为何会产生OutOfMemory产生?
答:一句话:Heap内存中没有足够的可用内存了。这句话要好好理解,不是说Heap没有内存了,是说新申请内存的对象大于Heap空闲内存,好比如今Heap还空闲1M,可是新申请的内存须要1.1M,因而就会报OutOfMemory了,可能之后的对象申请的内存都只要0.9M,因而就只出现一次OutOfMemory,GC也正常了,看起来像偶发事件,就是这么回事。 但若是此时GC没有回收就会产生挂起状况,系统不响应了。
问:我产生的对象很少呀,为何还会产生OutOfMemory?
答:你继承层次忒多了,Heap中 产生的对象是先产生 父类,而后才产生子类,明白不?
问:OutOfMemory错误分几种?
答:分两种,分别是“OutOfMemoryError:java heap size”和”OutOfMemoryError: PermGen space”,两种都是内存溢出,heap size是说申请不到新的内存了,这个很常见,检查应用或调整堆内存大小。
“PermGen space”是由于永久存储区满了,这个也很常见,通常在热发布的环境中出现,是由于每次发布应用系统都不重启,长此以往永久存储区中的死对象太多致使新对象没法申请内存,通常从新启动一下便可。
问:为何会产生StackOverflowError?
答:由于一个线程把Stack内存所有耗尽了,通常是递归函数形成的。
问:一个机器上能够看多个JVM吗?JVM之间能够互访吗?
答:能够多个JVM,只要机器承受得了。JVM之间是不能够互访,你不能在A-JVM中访问B-JVM的Heap内存,这是不可能的。在之前老版本的JVM中,会出现A-JVM Crack后影响到B-JVM,如今版本很是少见。
问:为何Java要采用垃圾回收机制,而不采用C/C++的显式内存管理?
答:为了简单,内存管理不是每一个程序员都能折腾好的。
问:为何你没有详细介绍垃圾回收机制?
答:垃圾回收机制每一个JVM都不一样,JVM Specification只是定义了要自动释放内存,也就是说它只定义了垃圾回收的抽象方法,具体怎么实现各个厂商都不一样,算法各异,这东西实在不必深刻。
问:JVM中到底哪些区域是共享的?哪些是私有的?
答:Heap和Method Area是共享的,其余都是私有的
问:什么是JIT,你怎么没说?
答:JIT是指Just In Time,有的文档把JIT做为JVM的一个部件来介绍,有的是做为执行引擎的一部分来介绍,这都能理解。Java刚诞生的时候是一个解释性语言,别嘘,即便编译成了字节码(byte code)也是针对JVM的,它须要再次翻译成原生代码(native code)才能被机器执行,因而效率的担心就提出来了。Sun为了解决该问题提出了一套新的机制,好,你想编译成原生代码,没问题,我在JVM上提供一个工具,把字节码编译成原生码,下次你来访问的时候直接访问原生码就成了,因而JIT就诞生了,就这么回事。
问:JVM还有哪些部分是你没有提到的?
答:JVM是一个异常复杂的东西,写一本砖头书都不为过,还有几个要说明的:
问:为何不建议在程序中显式的生命System.gc()?
答:由于显式声明是作堆内存全扫描,也就是Full GC,是须要中止全部的活动的(Stop The World Collection),你的应用能承受这个吗?
问:JVM有哪些调整参数?
答:很是多,堆内存、栈内存的大小均可以定义,甚至是堆内存的三个部分、新生代的各个比例都能调整。
在互联网公司面试中,架构的底层必定是面试官会问到的问题,针对面试官通常会提到的问题,我录制了一些底层原理的录像视频,加群:650385180能够免费获取这些录像,里面有些分布式,微服务,性能优化,Spring,MyBatis的等源码知识点的录像视频。上图的性能优化只是其中的一小部分,这些视频都是我找一些资深架构师朋友一块儿录制出来的,视频但愿可以帮助到如下几类程序员:
1.对如今的薪资不满,想要跳槽,却对本身的技术没有信心,不知道如何面对面试官。
2.想从传统行业转行到互联网行业,但没有接触过互联网技术。
3.工做1 - 5年须要提高本身的核心竞争力,但学习没有系统化,不知道本身接下来要学什么才是正确的,踩坑后又不知道找谁,百度后依然不知因此然。
4.工做5 - 10年没法突破技术瓶颈(运用过不少技术,在公司一直写着业务代码,却依然不懂底层实现原理)
若是你如今正处于我上述所说的几个阶段能够加下个人群来学习。并且我也可以提供一些面试指导,职业规划等建议。