1、JVM探究

  • 请你谈谈你对JVM的理解?java8虚拟机和之前的变化更新?
  • 什么是OOM,什么是栈溢出StackOverFlowError?怎么分析?
  • JVM的常用调优参数有哪些?
  • 内存快照如何抓取,怎么分析Dump文件?
  • 谈谈JVM中,类加载器你的认识?
  1. JVM的位置

  2. JVM的体系结构

  3. 类加载器

  4. 双亲委派机制

    /*
    1.类加载器收到类加载的请求!
    2.将这个请求向上委托给父类加载器去完成,一直向上委托,直到启动类加载器
    3.启动加载器检查是否能够加载当前这个类,能加载就结束,使用当前的加载器,狗则,抛出异常,通知子加载器进行加载
    4.重复步骤 3
    Class Not Found
    null: java调用不到,C\C++
    */

  5. 沙箱安全机制

    ​ Java安全模型的核心就是Java沙箱(sandbox),什么是沙箱?沙箱是一个限制程序运行的环境。沙箱机制就是将Java代码限定在虚拟机(JVM)特定的运行范围中,并且严格限制代码对本地系统资源访问,通过这样的措施来保证对代码的有效隔离,防止对本地系统造成破坏。沙箱主要限制系统资源访问,那系统资源包括什么?CPU、内存、文件系统、网络。不同级别的沙箱对这些资源访问的限制也可以不一样。

    ​ 所有的Java程序运行都可以指定沙箱,可以定制安全策略。

    ​ 在Java中将执行程序分成本地代码和远程代码两种,本地代码默认为可信任的,而远程代码则被看作是不受信任的。对于授信的本地代码,可以访问一切本地资源。而对于非授信的远程代码在早期的Java实现中,安全依赖于沙箱(sandbox)机制。如下图所示JDK1.0安全模型

    ​ 但如此严格的安全机制也给程序的功能扩展带来障碍,比如当用户希望远程代码访问本地系统的文件时候,就无法实现。因此在后续的Java1.1版本中,针对安全机制做了改进,增加了安全策略,允许用户指定代码对本地资源的访问权限。如下图所示JDK1.1安全模型

    ​ 在Java1.2版本中,再次改进了安全机制,增加了代码签名。不论本地代码或是远程代码,都会按照用户的安全策略设定,由类加载器加载到虚拟机中权限不同的运行空间,来实现差异化的代码执行权限控制。如下图所示JDK1.2安全模型

    ​ 当前最新的安全机制实现,则引入了域(Domain)的概念。虚拟机会把所有代码加载到不同的系统域和应用域,系统域部分专门负责与关键资源进行交互,而各个应用域部分则通过系统域的部分代理来对各种需要的资源进行访问。虚拟机中不同的受保护域(Protected Domain),对应不一样的权限(Permission)。存在于不同域中的类文件就具有了当前域的全部权限,如下图所示最新的安全模型(jdk1.6)

    组成沙箱的基本组件:

    • 字节码校验器(bytecode verifier):确保Java类文件遵循Java语言规范。这样可以帮助Java程序实现内存保护。但并不是所有的类文件都会经过字节码校验,比如核心类。
    • 类加载器(class loader):其中类装载在三个方面对Java沙箱起作用
      • 它防止恶意代码去干涉善意的代码;
      • 它守护了被信任的类库边界;
      • 它将代码归入保护域,确定了代码可以进行哪些操作。

    ​ 虚拟机为不同的类加载器载入的类提供不同的命名空间,命名空间由一系列唯一的名称组成,每一个被装载的类将有一个名字,这个命名空间是由Java虚拟机为每一个类装载器维护的,它们互相之间甚至不可见。

    ​ 类装载器采用的机制是双亲委派模式。

    1. 从最内层JVM自带类加载器开始加载,外层恶意同名类得不到加载从而无法使用;
    2. 由于严格通过包来区分了访问域,外层恶意的类通过内置代码也无法获得权限访问到内层类,破坏代码就自然无法生效。
    • 存取控制器(access controller):存取控制器可以控制核心API对操作系统的存取权限,而这个控制的策略设定,可以由用户指定。
    • 安全管理器(security manager):是核心API和操作系统之间的主要接口。实现权限控制,比存取控制器优先级高。
    • 安全软件包(security package):java.security下的类和扩展包下的类,允许用户为自己的应用增加新的安全特性,包括:
      • 安全提供者
      • 消息摘要
      • 数字签名
      • 加密
      • 鉴别
  6. Native

    //native : 凡是带了native关键字的,说明java的作用范围打不到了,会去调用底层C语言的库!
    //会进入本地方法栈 Native Method Stack
    //调用本地方法本地接口 JNI
    //JNI的作用:扩展Java的使用,融合不同的编程语言为Java所用!最初:C\C++。
    //Java诞生的时候 C/C++横行,想要立足,必须要有调用C/C++的程序~
    //它在内存区域中专门开辟了一块标记区域:Native Method Stack,登记native方法
    //在最终执行的时候,加载本地方法库中的方法通过JNI
    //Java程序驱动打印机,管理系统,掌握即可,企业级应用中较为少见!
  7. PC寄存器

    PC寄存器(计数器)

    程序计数器:Program Counter Register

    ​ 每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向下一条指令的地址,也即将要执行的指令代码),在执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计

  8. 方法区

    方法区

    Method Area 方法区

    ​ 方法区是被所有线程共享,所有字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义,简单说,所有定义的方法的信息都保存在该区域,此区域属于共享区间

    ​ 静态变量、常量、类信息(构造方法、接口定义)、运行时的常量池存在方法区中,但是实例变量存在堆内存中,和方法区无关

    static final Class模板 字符串常量池;

    jdk1.8后static,字符串常量池保存在堆中

  9. 栈:数据结构

    栈:先进后出,后进先出:桶

    队列:先进先出(FIFO:First Inpu First Output)

    为什么main()先执行,最后结束~ 栈:栈内存,主管程序的运行,生命周期和线程同步;

    线程结束,栈内存也就释放,对于栈来说,不存在垃圾回收问题,一旦线程结束,栈就Over

    栈:8大基本类型 + 对象引用 + 实例的方法

    栈 + 堆 + 方法区 :交互关系

  10. 三种JVM

    • Sun公司 HotSpot Java HotSpot(TM) 64-Bit Server VM (build 25.301-b09, mixed mode)
    • BEA JRockit
    • IBM J9 VM

    我们学习的都是:HotSpot

  11. Heap,一个JVM只有一个堆内存,堆内存的大小是可以调节的。

    类加载器读取了类文件后,一般会把什么东西放到堆中? 类,方法,常量,变量~,保存我们所有引用类型的真实对象;

    堆内存中还要细分为三个区域:

    • 新生区(伊甸园区) Young/New
    • 养老区 old
    • 永久区 Perm

    GC 垃圾回收,主要是在伊甸园区和养老区~

    假设内存满了,OOM,堆内存不够! java.lang.OutOfMemoryError: Java heap space

    在JDK8以后,永久存储区改了个名字(元空间);

  12. 新生区、老年区

    新生区

    • 类:诞生和成长的地方,甚至死亡
    • 伊甸园,所有的对象都是在伊甸园区new出来的!
    • 幸存者区(0,1)

    老年区

  13. 永久区

    永久区:这个区域常驻内存的,用来存放JDK自身携带的Class对象。Interface元数据,存储的是Java运行时的一些环境或类信息,这个区域不存在垃圾回收!关闭虚拟机(VM)就会释放这个区域的内存

    一个启动类,加载了大量的第三方jar包。Tomcat部署了太多的应用,大量动态生成的反射类。不断地被加载。直到内存满,就会出现OOM(OutOfMemoryError);

    // 默认情况下:分配的总内存是电脑内存的1/4,而初始化的内存:1/64
    // OOM异常处理方法:
    // 1.尝试扩大堆内存看结果
    // 2.分析内存,看一下哪个地方出了问题(专业工具)
    // -Xms1024m -Xmx1024m -XX:+PrintGCDetails
    • jdk1.6之前 :永久代,常量池是在方法区;
    • jdk1.7 :永久代,但是慢慢退化了,去永久代,常量池在堆中
    • jdk1.8之后 :无永久代,常量池在元空间

    元空间:逻辑上存在,物理上不存在

    在一个项目中,突然出现了OOM故障,那么该如何排除研究为什么出错

    • 能够看到代码第几行出错:内存快照分析工具,MAT,Jprofiler
    • Dubug,一行行分析代码!

    MAT,JProfiler作用:

    • 分析Dump内存文件,快速定位内存泄漏;
    • 获得堆中的数据
    • 获得大的对象~
    • ...

    JProfiler界面:

  14. 堆内存调优

  15. GC

    JVM在进行GC时,并不是对这三个区域统一回收。大部分时候,回收都是新生代~

    • 新生代
    • 幸存区(from ,to)
    • 老年区

    GC两种类:轻GC(普通的GC),重GC(全局GC)

    题目:

    • JVM的内存模型和分区~详细到每个区放什么?
    • 堆里面的分区有哪些?Eden,from,to,老年区,说说他们的特点!
    • GC的算法有哪些?标记清除法,标记压缩,复制算法,引用计数法,怎么用的?
    • 轻GC和重GC分别在什么时候发生?

    引用计数法:

    复制算法:

    • 好处:没有内存的碎片
    • 坏处:浪费了内存空间~,多了一半空间永远是空to。假设对象100%存活(极端情况)

    复制算法最佳使用场景:对象存活度较低的时候;新生区~

    标记清除算法:

    • 优点:不需要额外的空间!
    • 缺点:两次扫描,严重浪费时间,会产生内存碎片。

    标记压缩算法

    再优化:

    标记清除压缩算法

    先对要扫描的对象进行几次标记清除算法处理

    再压缩

  16. JMM:Java Memory Model

    1. 什么是JMM?

      JMM:(Java Memory Model的缩写)

    2. 它干嘛的? 官方,博客,对应的视频

      作用:缓存一致性协议,用于定义数据读写的规则(遵守,找到这个规则)。

      JMM定义了线程工作内存和主内存之间的抽象关系:线程之间的共享变量存储在主内存(Main Memory)中,每个线程都有一个私有的本地内存(Local Memory)

      解决共享对象可见性这个问题:volatile

    3. 它该如何学习?

      JMM:抽象的概念,理论

      JMM对这八种指令的使用,制定了如下规则:

      • 不允许read和load、store和write操作之一单独出现。即使用了read必须,使用了store必须write
      • 不允许线程丢弃它最近的assign操作,即工作变量的数据改变了之后,必须告知主存
      • 不允许一个线程将没有assign的数据从工作内存同步回主内存
      • 一个新的变量必须在主内存中诞生,不允许工作内存直接使用一个未被初始化的变量。就是对变量实施use、store操作之前,必须经过assign和load操作
      • 一个变量同一时间只有一个线程能对其进行lock。多次lock后,必须执行相同次数的unlock才能解锁
      • 如果对一个变量进行lock操作,会清空所有工作内存中此变量的值,在执行引擎使用这个变量前,必须重新load或assign操作初始化变量的值
      • 如果一个变量没有被lock,就不能对其进行unlock操作。也不能unlock一个被其他线程锁住的变量
      • 对一个变量进行unlock操作之前,必须把此变量同步回主内存

      JMM对这八种操作规则和对volatile的一些特殊规则就能确定哪些操作是线程安全,哪些操作是线程不安全的了。但是这些规则实在复杂,很难在实践中直接分析。所以一般我们也不会通过上述规则进行分析。更多的时候,使用java的happen-before规则来进行分析。

      volatile:解决一致性


  17. 总结

    内存效率:复制算法>标记清除算法 >标记压缩算法(时间复杂度)

    内存整齐度:复制算法=标记压缩算法>标记清除算法

    内存利用率:标记压缩算法=标记清除算法>复制算法

    思考一个问题:难道没有最优算法吗?

    答案:没有,没有最好的算法,只有最合适的算法 ------> GC :分代收集算法

    年轻代:

    • 存活率低
    • 复制算法!

    老年代:

    • 区域大:存活率高
    • 标记清除(内存碎片不是太多) + 标记压缩 混合实现

一天时间学JVM不现实,要深究必须要下去花时间和多看《深入理解JVM虚拟机》及面试题

但是我们可以掌握一个学习JVM的方法~

JVM探究的更多相关文章

  1. JVM探究之 —— 垃圾回收(一)

    垃圾收集(Garbage Collection,GC),大部分人都把这项技术当做Java语言的伴生产物.事实上,GC的历史比Java久远,1960年诞生于MIT的Lisp是第一门真正使用内存动态分配和 ...

  2. JVM探究——转载

    JVM探究 请你谈谈你对JVM的理解 Java8虚拟机和之前的变化更新 什么式OOM,什么是栈溢出StackOverFlowError?怎么分析 JVM的常用调优参数有哪些? 内存快照如何抓取,怎么分 ...

  3. 第43天学习打卡(JVM探究)

    JVM探究 请你谈谈你对JVM的理解?Java8虚拟机和之前的变化更新? 什么是OOM,什么是栈溢出StackOverFlowError? 怎么分析? JVM的常用调优参数有哪些? 内存快照如何抓取, ...

  4. JVM探究(一)谈谈双亲委派机制和沙箱安全机制

    JVM探究 请你谈谈你对JVM的理解?java8虚拟机和之前的变化gengxin? 什么是OOM,什么是栈溢出StackOverFlowError JVM的常用调优参数有哪些? 内存快转如何抓取,怎么 ...

  5. JVM探究 面试题 JVM的位置 三种JVM:HotSpot 新生区 Young/ New 养老区 Old 永久区 Perm 堆内存调优GC的算法有哪些?标记清除法,标记压缩,复制算法,引用计数法

    JVM探究 面试题: 请你弹弹你对JVM的理解?Java8虚拟机和之前的变化更新? 什么是OOM?什么是栈溢出StackOverFlowError?怎么分析 JVM的常用调优参数有哪些? 内存快照如何 ...

  6. JVM探究之 —— 类加载器-双亲委派模型

    虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类.实现这个动作的代码模块称为“类加载器 ...

  7. JVM探究之 —— 垃圾回收(二)

    1. 垃圾收集算法 1.1 标记清除(Mark-Sweep)算法 标记—清除算法是第一种使用和比较完善的垃圾回收算法,后续的收集算法都是基于其设计思路并对其不足进行改进而得到的. 该算法分为“标记”和 ...

  8. JVM探究之 —— Java内存区域

    1. 概述 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们既是拥有最高权力的“皇帝”又是从事最基础工作的“劳动人民”——既拥有每一个对象的“所有权”,又担负着每一个对象生命开始到终结的 ...

  9. JVM探究之 —— OOM异常

    在Java虚拟机规范的描述中,除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError(下文称OOM)异常的可能.本节探究主要基于jdk1.8的内存结构. 1. Jav ...

随机推荐

  1. TreeMap与TreeSet的源码分析

    1.TreeMap源码 1.属性部分: private final Comparator<? super K> comparator;//比较器 private transient Ent ...

  2. jQuery--内容过滤和可见性过滤

    一.内容过滤 1.内容过滤选择器介绍 :empty 当前元素是否为空(是否有标签体) :contains(text)   标签体是否含有指定的文本 :has(...)                 ...

  3. Mybatis框架基础入门(二)--架构简介

    mybatis配置 SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息. mapper.xml文件即sql映射文件,文件中配置了操作数据库的 ...

  4. 使用SpringDataJdbc无法注册的情况

    当 EnableJdbcRepositories 注解无法注册Repository仓库的时候,你可以查看下 你的实体是否存在@Table注解,没有请加上,这样就能扫描到了 @Table("b ...

  5. 学习GlusterFS(四)

    基于 GlusterFS 实现 Docker 集群的分布式存储 以 Docker 为代表的容器技术在云计算领域正扮演着越来越重要的角色,甚至一度被认为是虚拟化技术的替代品.企业级的容器应用常常需要将重 ...

  6. element-ui 无法对绑定表单的对象中的对象属性进行验证

    <el-form-item label="类型" :label-width="formLabelWidth" prop="typeId" ...

  7. 8_LQR 控制器_状态空间系统Matlab/Simulink建模分析

    再线性控制器中讲到: 举例说明(线性控制器中的一个例子)博客中有说明 在matlab中:使用lqr求解K1.K2 这里希望角度(即x1)能迅速变化,所以Q矩阵中Q11为100,并没有关心角速度(dot ...

  8. 顺利通过EMC试验(2)

    限制值 电磁波照射,静电放电敏感性

  9. 纯CSS实现柱形图

    CSS在处理排版之强大,没有做不到,只有想不到.下面我们将一同实现一个柱状图. 先打好一个具体的框架.我们利用无序列表做整体,里面的东西我们根本选择内联无素span,strong,em来填充. < ...

  10. 前端面试题整理——手写bind函数

    var arr = [1,2,3,4,5] console.log(arr.slice(1,4)) console.log(arr) Function.prototype.bind1 = functi ...