JVM入门
面试过程中,问到JVM一脸懵逼,在github看了一些文章,感觉质量不错,整理了一下希望大家不吝赐教。
目前主流的jdk采用解释与编译混合执行的模式,其JIT技术采用分层编译,极大地提升了Java的执行速度
刚学习Java的时候,提到Java是一次编写,到处运行”(Write once, run anywhere),当时只是粗略记住了,那么怎么实现的呢?
1.如何实现跨平台?
首先,计算机工程领域任何问题,都可以通过增加一个中间层来解决。Java的中间码就是“字节码(Bytecode)”,Java所有的指令有200个左右一个字节可以存储256种不同指令的信息。代码执行过程中,JVM将字节码解释执行,屏蔽对底层操作系统的依赖,JVM也可以将字节码编译执行,如果是热点代码,会通过JIT动态地编译为机器码,提高执行效率。
2.字节码的执行流程
字节码必须通过类加载到JVM环境中,才可以执行。执行有三种模式:
1.解释执行
2.JIT编译执行
3.JIT编译与解释混合(大多数主流JVM采用的方案)
混合执行模式的优势在于解释器在启动时先解释执行,省去编译时间。随着时间推进,JVM通过热点代码统计分析,识别高频方法的调用、循环体、公共模块等,基于强大的JIT动态编译技术,将热点代码转换成机器码,直接交给CPU执行。JIT作用就是将字节码动态地编译成可以直接发送给处理器指令执行的机器码。

即时编译流程
3.类怎么加载的(双亲委派机制)
首先,低层次的当前类加载器,不能覆盖更高层次类加载器已将加载的类。如果低层次的类想加载一个未知类,要非常礼貌的向上级询问:请问这个类已经加载了吗? 被询问的高层次类加载器会自问两个问题:
- 我是否已经加载过此类?
- 如果没有可否加载此类
如果回答都是否定的,才可以加载这个未知类。
4.JVM调优的原则
- GC的时间足够小
- GC的次数足够少
- 发生Full GC的周期足够长
前两个是相悖的,要想GC时间小必须要一个更小的堆,要保证GC的次数足够少,必须保证更大的堆,只能取其平衡
(1)针对JVM堆的设置,通过 -Xms -Xmx 限定其最小值和最大值,为了防止,垃圾收集器在最小最大之间收缩堆而产生额外的时间,通常把最大最小设为相同的值
(2) 年轻代和老年代将根据默认的比例(1:2)分配堆内存,可以通过调整二者之间的比率NewRadio调整二者的大小。
(3)年轻代和老年代设置多大才算合理?
没有固定答案。
整个JVM内存大小 = 年轻代大小 + 老年代大小 + 持久代大小。
持久代大小一般为64M,增大年轻代后,将会减小老年代的大。此值对系统性能影响较大,Sun官方推荐将年轻代调整为整个堆的 3/8
(4)配置较好的机器上(多核,大内存),可以为老年代选择并行收集算法 -XX:+UseParallelOldGC ,默认为 Serial 收集
(5) 线程堆栈的设置:每个线程默认会开启1M的堆栈。用于存放栈帧、调用参数、局部变量等,减小这个值能生成更多的的线程,但操作系统对一个进程内的线程数有限制,不能无限生成,一般在3000~5000左右
5. 对象分配规则
- 对象优先分配在Eden区,如果Eden区没有足够的空间时,虚拟机执行一次Minor GC.
- 大对象直接进入老年代(大对象是指需要大量连续内存空间的对象)。避免在Eden区和Survior区之间发生大量的内存拷贝
- 长期存活的对象进入老年代。虚拟机为每个对象定义了一个年龄计数器,对象经过一次Monior GC对象会进入Survivor区,之后每经过一次Minor GC那么对象年龄增加1,直到达到阀值后进入老年代
- 动态判断对象的年龄。如果Survivor区中有相同年龄的对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象直接进入老年代。
- 空间分配担保。每次进行Monitor GC时,JVM会计算Survivor区移动至老年区的对象的平均大小,如果这个值大于老年区的剩余值的大小则进行一次 Full GC,如果小于就检查HandlerPromonitorFailure设置,如果true则只进行Monitor GC,false则进行Full GC
JVM入门的更多相关文章
- JVM入门——运行时数据区
这张图我相信基本上对JVM有点接触的都应该很熟悉,可以说这是JVM入门的第一课.其中的“堆”和“虚拟机栈(栈)”更是耳熟能详.下面将围绕这张图对JVM的运行时数据区做一个简单介绍. 程序计数器(Pro ...
- JVM入门到放弃之基本概念
1. 基本概念 jvm 是可运行Java代码的假想计算机,包括一套字节码指令集.一组寄存器.一个栈.一个垃圾回收堆和一个存储方法域. jvm 是运行在操作系统之上的,屏蔽了与具体操作系统平台相关的信息 ...
- JVM 入门三板斧
一个JVM实例只存在一个堆内存,堆内存的大小是可以调节的.类加载器读取了类文件后,需要把类.方法.常变量放到堆内存中,保存所有引用类型的真实信息,以方便执行器执行,堆内存分为三部分: Young Ge ...
- java jvm入门 jvm什么意思 jvm调优
接下来我会给大家讲解 国内最顶尖的jvm技术 不服来战
- JVM入门——JVM内存结构
一.java代码编译执行过程 1.源码编译:通过Java源码编译器将Java代码编译成JVM字节码(.class文件) 2.类加载:通过ClassLoader及其子类来完成JVM的类加载 3.类执行: ...
- 2017.10.9 JVM入门学习
1.什么是JVM JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现 ...
- JVM 入门指南
一.什么是JVM? JVM: JVM是Java Virtual Machine的缩写,中文翻译为Java虚拟机.JVM 可以看作一台抽象的计算机,如同真实的计算机一样,它有自己的指令集和各种运行时区域 ...
- JVM入门必看——JVM结构
转载自:http://blog.csdn.net/yfqnihao 这一节,主要来学习jvm的基本结构,也就是概述.说是概述,内容很多,而且概念量也很大,不过关于概念方面,你不用担心,我完全有信心,让 ...
- jvm入门及理解(一)——简介与体系架构
最近,在学习java虚拟机的内容中,在此总结和记录下学到的. 一.JVM在计算机中的位置 在我们初学java时,便知道java源文件文件会先通过Java编译器编译成字节码文件,这个过程是java编译过 ...
随机推荐
- ubuntu中连接mssql数据库sqlserver
参考文章 https://blog.csdn.net/fangaoxin/article/details/5386149 (感谢作者) sudo apt-get install tdsodbc sud ...
- php_screw安装,使用
安装步骤:1. 下载源码:wget http://nchc.dl.sourceforge.net/project/php-screw/php-screw/1.5/php_screw-1.5.tar.g ...
- pdf.js的使用
下载地址: files.cnblogs.com/zycjwdss/mypdf.zip 把下载后的zip解压,放到web服务器根目录下,打开pdf.html,把这一句取消注释: //window.pd ...
- Spring3基础原理解析
一.Spring3主要含义 Spring3是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架. 注:IOC的作用:对象依赖的其他对象通过被动的形式传递进来而不是这个对象常见或者查找依赖对象 ...
- Python3.4 枚举类型的使用
From: https://majing.io/posts/10000005131196 枚举类型是在Python3.4新增到Python的标准库. 创建枚举 Python提供了两种方法来创建枚举: ...
- Python高级变量类型
1.列表基础操作 2.列表循环遍历 3.元组 4.字典基础操作 5.字典循环遍历 6.字符串基础操作 7.字符串切片 8.公共方法
- three.js的raycaster射线无法获取visible为false的网格对象
在做网格对象拖放时,需要创建一个不可见的参考平面,如果将平面对象设置为visible,则射线对象无法获取该平面,就无法进行位置计算. onDocumentMouseMove: function (e) ...
- 基于STM8的UART发送和中断接收---STM8-第二章
1. 综述 UART的基础知识,通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),通常称作UART,是一种异步收发传输器. 做软件开发的人都 ...
- C++日常应用-定时器
定时器的使用:分为有句柄 无句柄两类 有句柄情况下的使用:头文件: 1.添加映射 BEGIN_MSG_MAP(类名) MESSAGE_HANDLER(WM_TIMER, OnTimer) END_MS ...
- php redis 操作
在php里边,redis就是一个功能类,该类中有许多成员方法(名字基本与redis指令的名字一致,参数也一致). 实例: <?php $redis = new Redis(); //连接本地的 ...