高级程序员必须掌握的JVM知识点

1、JVM基础知识

1.1 java是如何实现跨平台的

Java的跨平台指的是java语言的跨平台,而不是JVM。JVM是由C/C++开发的,是编译后的机器码,JVM不能跨平台,不一样平台须要安装不一样版本的JVM。
咱们编写的java源码经过编译后会生成字节码文件(以.class结尾)。JVM就是负责将这些字节码文件翻译成特定平台下的机器语言而后执行。也就是说在不一样平台,咱们只要安装对应的JVM,就能够运行咱们的字节码文件,实现一次编译,处处运行的目的。在整个架构中,JVM起到一个中间层的做用。java

1.2 什么是JVM

JVM,即java virtual machine ,java 虚拟机。它经过模拟一个计算机来实现计算机所具备的运算功能。它能够跨计算机体系来运行java字节码文件,主要缘由是它屏蔽了各个计算机系统之间先关软件和硬件的差别,使得与平台相关的耦合统一由JVM来实现。程序员

1.3 JVM由那些部分组成

JVM由4个重要的组成部分,类加载器、执行引擎、内存区及本地方法调用。
类加载器: 在JVM启动或者类运行时将须要的.class文件加载到JVM中。类加载器负责读取java字节码并转化成java.lang.Class类的一个实例,每一个这样的实例用来表示一个Java类。经过此实例的newInstance()方法,就能够构建该类的一个实例对象。
JVM经过看类的全名和类的加载器是否同样来判断是否属于同一个类。只有二者都相同的时候才认为是同一个类。即使类的字节码是同样的,不一样的类加载器加载以后的获得的类也是不同的。
类加载器加载.class文件到JVM须要通过如下步骤。加载->验证->准备->解析->初始化->使用->卸载。这个过程能够划分为三个阶段。一、第一个阶段是找到.class文件并将这个文件中包含的字节码加载到JVM中。二、第二个阶段分为三个步骤,分别是字节码验证、类数据结构分析及相应的内存分配和符号表的连接。三、第三个阶段是类中的静态属性和初始化赋值,以及静态模块的执行。web

执行引擎: 执行引擎的任务时负责执行.class文件中的字节码指令,至关于计算机的CPU。
内存区: 将内存划分为多个区以模拟实际机器上的存储、记录和调度功能模块。功能相似于实质计算中上的各类寄存器和PC指针记录器等。
本地方法调用: 调用C/C++实现的本地方法的代码返回结果算法

1.4 常见问题

2、JVAM内存管理

JVM的内存划分为方法区、堆内存、程序计数器、虚拟机栈和本地方法栈。
方法区: 线程共享,各个线程共享的一个区域,用于存储虚拟机加载的类信息、常量、静态变量、编译器编译后的代码等数据。Java虚拟机规范将方法区描述为堆的一个逻辑部分,它还有一个别名Non-Heap(非堆),猜想应该是为了与java堆区分开。运行时常量时是属于方法区的一个部分,用于存放编译过程产生的各类字面变量和符号引用。数据结构

**堆内存:**全部线程共享区域,垃圾收集管理器主要做用区域。目前主要的垃圾回收算法是分代收集算法,因此Java堆中还能够细分为新生代和老年代。在细致一点又能够划分为:Eden空间、From Survivor空间和To Survivor空间,默认状况下按照8:1:1比例进行分配。根据虚拟机的规范规定,java堆能够属于物理上不连续的内存空间中,只要逻辑上连续便可。
程序计数器: java线程私有,相似于操做系统中的PC计数器,它能够看作是当前执行线程的字节码的行号指示器。若是线程执行的是一个java方法,那么这个计算器记录的是正在执行的虚拟机指令地址;若是正在执行的是一个native方法,这个计数器的值是空的。此内存区域是java规范中惟一一个没有规定任何OutOfMemoryError的区域。
虚拟机栈: java线程私有,虚拟机栈描述的是java方法执行的内存模型。每一个方法在执行的时候,都会构建一个栈用于存储局部变量、操做数、动态连接、方法出口等信息。每个方法的执行都意味着一个栈贞在虚拟栈中入栈到出栈的过程。
本地方法栈: 和java虚拟机栈相似。区别是该区域为JVM提供使用native方法服务。架构

2.1 对象分配原则

  1. 对象优先分配到Eden区,若是Eden没有足够的空间时,系统会执行一次GC。
  2. 大对象(须要大量连续内存空间的对象)直接进入老年代,这样作的目的是避免Eden区和两个Survivor区发生大量的内存拷贝。
  3. 长期存活的对象进入老年代,JVM为每个对象定义了一个年龄计数器,若是对象经历了一次GC,那么对象就会进入Survivor区,以后每经理一次GC,年两就会+1,到达阈值的对象进入老年区。
  4. 动态判断对象的年龄,若是Survivor区中相同年龄的全部对象大小总和大于Survivor空间的一半,年龄大于或等于该年龄的对象直接进入老年代。
  5. 空间分配担保,每次GC,JVM会计算Survivor移入老年区对象的平均大小,若是这个值大于老年代剩余值的大小,那么就会进行一次Full GC。若是小于就会检查HandlePromotionFailure设置,若是true则只进行GC,若是是false,进行Full GC。

2.2 Java内存模型

JVM规范中试图定义一种Java内存模型(java Memory Model,JMM)来屏蔽硬件和操做系统间访问内存的差别,以实现java程序在各个平台下都能一致访问内存的效果。
Java内存模型规范了全部的变量都存储在主内存(Main Memory)中。每一个线程有本身的工做内存(working memory),工做内存中保存了当前线程使用到的变量的主内存副本拷贝,线程对变量的错有操做(读取、赋值等)都必须在主内存中进行,而不能直接读写与主内存中的变量。线程间的变量值的传递仅须要经过主内存来完成。并发

2.3 内存屏障

内存屏障又称为内存栅栏,是一组处理器指令,用于实现对内存操做顺序的限制。svg

2.4 内存泄漏和内存溢出

内存溢出: 指内存不够用了,
内存泄漏: 指对象可达,可是没有用了,即本该GC回收的对象可是并无被回收。内存泄漏是致使内存溢出的缘由之一,内存泄漏累积会致使内存溢出。内存泄漏的缘由操作系统

  1. 长生命周期的对象引用对生命周期的对象。
  2. 没有将无用的对象设置为null

3.5 内存设置

-Xms 初始内存分配,默认是物理内存的1/64
-xmx 最大内存分配,默认是物理内存的1/4
–xx:PermSize 非堆内存的初始值,默认是物理内存的1/64
–xx:MaxPermSize 非堆内存的最大值,默认是物理内存的1/4
-Xmn2G 设置年轻代大小为2G
-XX:SurvivorRatio 设置年轻代中Eden和Sruvivor的比值线程

3.6 线程间的通讯

在共享线程模型里,线程之间共享程序的公共状态,线程之间经过读写内存中的公共状态来隐式通讯。 在消息传递并发模型里,线程之间没有公共状态,线程之间经过明确的收发消息来显示的进行通讯,在java中典型的线程通讯就是经过wait()和notiry()。