Java虚拟机内存模型(Java运行在虚拟机之上,虚拟机帮Java屏蔽底层的指令集,让Java能够跨平台运行)

  • 内存模型以及分区,需要详细到每个区放什么?

    • 方法区(method area): 方法信息
    • 本地方法栈(native method area): 本地方法
    • 堆(heap): 堆在内存中并不是一块连续的区域,物理上是分散的,但逻辑上是连续的,遇到一条new的指令时,为新生对象分配内存空间,有两种方式,指针碰撞,空间列表
      • 指针碰撞: 将内存逻辑上分为两边,一边是空闲的,一边是在用的,指针指向分界点,当需要分配内存的时候只要移动指针即可,只适用于内存规整的情况
      • 空间列表: 虚拟机必须维护一个列表,用于记录哪些内存是可用的,在需要进行分配的时候,就从列表中找出一块足够大的空间进行分配并更新列表
    • 栈(stack): 主要用来存放基本类型变量,局部变量以及对象的引用,方法的调用出入,栈的内存区域是连续的,有大小限制的,如果超出了就会抛出stackOverflowError异常,每个方法的调用都会对应着一个栈帧,有栈帧的入栈就有栈帧的出栈
  • 堆是存放对象以及数组的区域,分为年轻代和年老代
    • 年轻代又被分为一个Eden和两个Survivor区,即伊甸园和存活区
    • 假设有10个方格,则其中8个是Eden区,两个是Survivor区
    • 对象会在Eden区创建,当这两个区满了之后会将还存活的对象复制到另一个空白区Minor GC. 年轻代的对象有98%都是朝生夕死的
    • 如果年轻代不够放了,就放在年老代
    • 还有一种情况,对象在年轻代中存活的太久了
    • 每当进行一次复制回收的时候,还在年轻代中存活的对象就会加1岁,默认15岁就到年老代
    • 标记--清除--整理(标记好了就清除掉,最后整理成逻辑连续的区域)
    • 年老代存活的一般是大对象或很难死去的对象
    • 堆的设置
      • -Xms 10 m 堆的最小内存 10M
      • -Xmx 10 m 堆的最大内存 10M
      • -Xmn 10 m 设置新生代的内存大小
  • Java中GC标记(Garbage Collection)
    • 标记就是对一些已死的对象打上记号,有以下两种方法

      • 引用计数: 实现起来比较简单,就是给对象添加一个引用计数器,每当有一个地方引用它时就加1,引用失效时就减1,当计数器为0时就标记可回收,但很多主流的虚拟机并没有采用这种方法,因为它很难解决几个对象之间循环引用的问题
      • 可达性分析: 通过将一些称为“GC Roots”的对象作为起始点,从这些节点开始搜索和该节点发生直接或者间接引用关系的对象,将这些对象以链的形式组合起来,形成一张“关系网”,又叫做“引用链”,最后垃圾回收器就回收一些不在这张关系网上的对象
        • 栈帧中的引用对象(栈中的)
        • 静态属性引用的对象(方法区中的)
        • 常量引用的对象(方法区中的)
        • 本地方法栈中JNI引用的对象(本地方法栈中的)
  • Java中鲜为人知的二次标记
    • 所有的类都继承了Object类,因此,也默认实现了finalize方法。在该对象被回收之前,该对象的finalize方法会被调用。这里的被回收之前指的就是被标记之后,如果开发者重写了finalize方法,则该对象会被重新加入到引用链,即关系网中。面对同一个对象,他的finalize方法只会被调用一次
    • 二次标记
      • 第一次标记不在“关系网”中的对象
      • 第二次的话,就要先判断该对象有没有重写finalize方法
        • 如果没有,就直接回收
        • 如果重写了,则先放到一个队列中,并由虚拟机建立一个低优先级的线程来执行它,随后进行第二次小规模标记
  • 从GC日志分析堆内存
    • 由于GC线程和程序线程是并发执行的,当GC线程标记好了一个对象,此时程序中的线程又将该对象重新加入到了引用链中,虚拟机的解决办法是在一些特定位置设置一些“安全点”,当程序运行到这些“安全点”的时候就会暂停所有当前运行的线程(Stop The Word, STW), 暂停后重新找“GC Roots"进行关系的重建
    • 常见安全点的位置
      • 循环的末尾
      • 方法临返回前/调用方法的call指令后
      • 可能抛出异常的位置
    • 找到”GC Roots"也是花很长时间的,通过采用一个OopMap的数据结构来记录系统中存活的“GC Roots", 通过解释OopMap就可以找到堆中的对象,这种方式也叫准确式GC
    • GC和full GC是针对整个堆以及永久代的,时间长,尽量减少full GC的次数
  • Java中年轻代收集器(采用复制的收集算法)
    • Serial收集器: 一个单线程收集器,在进行回收的时候,必须暂停其它所有的工作进程,直到收集结束,用户体验不佳
    • ParNew收集器: 这个是Serial收集器的多线程版本,适用于多核CPU的设备
    • Parallel Scavenge收集器,默认的年轻代收集器,关注的是一个可控的吞吐量,吞吐量=运行代码的时间/(运行代码的时间+GC的时间),开启自适应调节策略
  • Java中年老代收集器,一般是大对象以及生命很顽强的对象(标记--清除--整理)
    • Serial Old收集器: 是Serial收集器的老年代版本,同样是单线程
    • Paraller Old收集器: 关注系统的吞吐量
    • CMS(Concurrent Mark Sweep)收集器: 是一种以最短停顿时间为目标的收集器
    • 标记
      • 初始标记----需要STW,直接关联
      • 并发标记----不需要STW,间接关联
      • 重新标记----需要STW,修改在上一步标记中有了变动的对象
      • 并发清除

初始Java虚拟机的更多相关文章

  1. 翻译Java虚拟机的结构

    英文原版:  https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html 直接谷歌翻译: Java SE规范 > Java虚拟机 ...

  2. 【深入Java虚拟机】之四:类加载机制

    类加载过程     类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载.验证.准备.解析.初始化.使用和卸载七个阶段.它们开始的顺序如下图所示: 其中类加载的过程包括了加载.验 ...

  3. JVM学习(1)——通过实例总结Java虚拟机的运行机制

    俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及到的知识点总结如下: JVM的历史 JVM的运行流程简介 JVM的组成(基于 Java 7) JVM调优参数:-Xmx和-Xms ...

  4. Elasticsearch Java 虚拟机配置详解

    Elasticsearch对Java虚拟机进行了预先的配置.通常情况下,因为这些配置的选择还是很谨慎的,所以你不需要太关心,并且你能立刻使用ElasticSearch. 但是,当你监视ElasticS ...

  5. 如何写出让java虚拟机发生内存溢出异常OutOfMemoryError的代码

    程序小白在写代码的过程中,经常会不经意间写出发生内存溢出异常的代码.很多时候这类异常如何产生的都傻傻弄不清楚,如果能故意写出让jvm发生内存溢出的代码,有时候看来也并非一件容易的事.最近通过学习< ...

  6. Java虚拟机浅探

    简介 对于java开发人员了来说,对java虚拟机肯定有着或多或少的了解.因为有了虚拟机的存在,才会使得java的内存管理变得那么方便,不再像C++那样使用new/delete来直接管理内存.知名的j ...

  7. Java虚拟机及运行时数据区

    1.Java虚拟机的定义 Java虚拟机(Java Virtual Machine),简称JVM.当我们说起Java虚拟机时,可能指的是如下三种不同的东西: 抽象的虚拟机规范 规范的具体实现 一个运行 ...

  8. 《深入理解Java虚拟机》垃圾收集器

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

  9. Java虚拟机各内存区域的位置及功能的介绍

    Java虚拟机运行时数据区: 相关区域介绍: 程序计数器: 功能:当前线程所执行字节码的行号指示器.若是Java方法记录指令地址,若为Native方法,则不记录 隔离性:线程隔离 Error:无 Ja ...

随机推荐

  1. linux 设备文件

    一.设备文件 在dev目录下 外部设备通过创建好的设备文件连接到服务器上,例如可以通过设备号给连接上去的硬件发消息. 二.设备文件分类 块设备 按块为单位,随机访问的设备 常见的有 硬盘 字符设备 按 ...

  2. spring学习(5)

    bean配置 启用注解 <context:annotation-config/> 使用spring的特殊bean 对bean BeanPostProcessor spring本身提供的特殊 ...

  3. MySQL查询in操作 查询结果按in集合顺序显示

    偶尔看到的...或许有人会注意过,但我以前真不知道 SQL: select * from table where id IN (3,6,9,1,2,5,8,7); 这样的情况取出来后,其实,id还是按 ...

  4. django中使用多个数据库,跨库查询

    一.settings配置多个数据库 DATABASES = { 'default': { # 'ENGINE': 'django.db.backends.mysql', 'ENGINE': 'comm ...

  5. 使用mybatis-generator插件结合tk.mybatis自动生成mapper二三事

    本篇文章将介绍使用spring boot框架,引入mybatis-generator插件,结合tk.mybatis自动生成Mapper和Entity的一整套流程,其中包括最重要的踩坑与填坑.     ...

  6. 12 Python 函数

    初识函数定义与调用 定义:def 关键词开头,空格之后接函数名称和圆括号(),最后还有一个":". def 是固定的,不能变,必须是连续的def三个字母,不能分开...它们要相亲相 ...

  7. linux命令学习笔记(14):head 命令

    head 与 tail 就像它的名字一样的浅显易懂,它是用来显示开头或结尾某个数量的文字区块,head 用来显 示档案的开头至标准输出中,而 tail 想当然尔就是看档案的结尾. .命令格式: hea ...

  8. 【leetcode刷题笔记】Remove Duplicates from Sorted Array II

    Follow up for "Remove Duplicates":What if duplicates are allowed at most twice? For exampl ...

  9. UML图之例图

    用例图主要说明的是谁要使用系统,以及他们使用该系统可以做些什么,帮助开发团队以一种可视化的方式理解系统的功能需求. 一个用例图包含了多个模型元素,如系统.参与者和用例,并且显示这些元素之间的各种关系, ...

  10. Python 爬虫闯关(第一关)

    在学习爬虫时,遇到了一个有意思的网站,这个网站设置了几个关卡,需要经过爬虫进行闯关,随着关卡的网后,难度不断增加,在闯关的过程中需要学习不同的知识,你的爬虫水平也自然随之提高. 今天我们先来第一关,访 ...