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. Python- 列表内置方法

    列表,元组 查 索引(下标) ,都是从0开始 切片 .count 查某个元素的出现次数 .index 根据内容找其对应的位置 "haidilao ge" in a 增加 a.app ...

  2. vs2017调用目标发生了异常

    解决办法: 1. 在开始菜单,找到“Visual Studio Tools”文件夹中的“VS 2017的开发人员命令提示符 ” 运行. 2. 输入:devenv /Safemode 3. 会以安全模式 ...

  3. Linux课程---6、别名管理和网络配置(Linux命令如何记)

    Linux课程---6.别名管理和网络配置(Linux命令如何记) 一.总结 一句话总结: 理解记忆:因为命令要实现那么多功能,必须有那么多参数,而不同的参数就适用不用的情况 命令基本格式:命令关键字 ...

  4. Appium-appium日志分析

    查看日志是很重要的一部分,我们在编辑器上测试代码时可以直接进行调试,但持续集成时程序自动运行,如果出现bug,只能通过日志来定位代码位置.appium日志主要分为三部分. 1. 准备阶段,包含了app ...

  5. 2017-2018-1 20179215《Linux内核原理与分析》第四周作业

    本次的实验是使用gdb跟踪调试内核从start_kernel到init进程启动,并分析启动的过程. 1.首先是在实验楼虚拟机上进行调试跟踪的过程. cd LinuxKernel qemu -kerne ...

  6. python密钥登录主机

    #!/usr/bin/python # -*- coding:utf-8 -*- ################################### # # 检查主机的损坏磁盘 # ####### ...

  7. bzoj 4031: 小Z的房间 矩阵树定理

    bzoj 4031: 小Z的房间 矩阵树定理 题目: 你突然有了一个大房子,房子里面有一些房间.事实上,你的房子可以看做是一个包含n*m个格子的格状矩形,每个格子是一个房间或者是一个柱子.在一开始的时 ...

  8. java判断一个类是否公共类

    Modifier.isPublic([类].getModifiers()) Modifier.isAbstract([类].getModifiers())

  9. jumpserver遇到的坑

    安装:https://github.com/jumpserver/jumpserver,看readme照着做就行,下面是遇到的坑.   0.4.4版坑: 1.要升级pip,否则有的包装不上   2.p ...

  10. C#创建DataTable的语法

    namespace EazyCMS.Web.admin { public partial class ceshi1 : System.Web.UI.Page { protected void Page ...