zoukankan      html  css  js  c++  java
  • 深入理解JAVA虚拟机-笔记

    一、JVM

      是整个Java平台的基石,是Java技术用于实现硬件与操作系统无关的关键部分,是保证用户机器免于恶意代码损害的屏障。

      可以被看做是一台抽象的计算机。 有⾃己的指令集和运行时的内存区域。

      与Java语⾔言并没有必然的联系。

        只有特定的二进制文件格式-Class文件格式关联。

        毕竟虚拟机其实只是一个程序,比我们写的hello world牛点。

    二、JVM的运⾏时内存区域划分

      语⾔言级别内存划分。

    page2image1682480page2image3684784page2image1622368page2image3679168page2image3678752page2image3693936page2image3677712page2image3697888page2image3697680

    1. 线程私有

    1.1. 程序计数器-pc 寄存器

      每个jvm线程都有⾃己的pc 计数器

      线程执⾏到的字节码的行号指示器,只要不是native方法, ⽤于执行过程中的循环、跳转、分⽀支、异常处理理线程恢复等。

      ⽣命周期与线程相同

    1.2. 虚拟机栈- stack

      描述的是⽅法执行的内存模型,⽅法的执行过程就是虚拟机栈的入栈与出栈

      用于存储局部变量和部分过程结果(些尚未算好的结果)的数据结构。

      也被用来处理动态链接、方法返回值和异常分派。

      生命周期与JVM线程相同,⽅法执⾏时都会创建⼀个栈帧。

      随着⽅法调⽤而创建,随着方法结束(⽆论正常还是异常完成)而销毁。

      局部变量表和操作数栈都是在编译期确定,在方法的code属性中。

      1.2.1. 局部变量表

        存放在编译时已经确定的8种基本类型、对象引用等。空间⼤小是确定的,

        在运行期间不会改变。

        ⽅法参数和局部变量

        局部变量 没有 初始化阶段,即不会被赋零值。

      1.2.2.操作数栈

        类似于数据寄存器
        方法开始执行时是空的, 运算过程中会有出栈入栈操作。

    1.3. 本地方法栈⽤

      用来⽀持native⽅法执⾏

      native关键字说明其修的⽅法是一个原⽣态方法,方法对应的实现不是在当前文件,⽽是在⽤其他语⾔(如C和C++)实现的文件中

    2. 线程共享

      2.1. 方法区

        是堆的一个逻辑部分 虚拟机启动时创建,1.8 已经开始直接使⽤用本地内存,元 空间。

        存储虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。 类的 版本信息等 字段 方法 接口等。 常量池。- 运⾏行行时常量池。 类、实例例、接口初始化时⽤用 到的特殊方法。

        不严谨的说,包含整个程序永远唯一的元素。

      2.2. Java 堆 -heap

        可供各个线程共享的运行时内存区域。

        最⼤的⼀块 ⼤小可以是固定的,也可以是动态的。 虚拟机启动时创建 几乎所有对象与数组都在堆上分配。

        可能会划分出多个线程私有的分配缓冲区 TLAB

      2.3 直接内存

        虚拟机规范外的内存区域,如NIO直接使⽤用的堆外内存。

     

    三、内存回收特殊的内存模块-不需回收或回收效率低

        线程私有的的内存:程序计数器、虚拟机栈、本地方法栈,随着线程生灭,分 配和回收都是确定的。

        永生代,就是前⾯面说的方法区,回收的效率很低。 现已改为 元空间,直接使⽤用的是本地内存。回收的两个内容为:

        1. 废弃常量 没有任何⼈人⽤用

        2. ⽆用的类 条件比较苛刻

          1. 该类的所有实例都已经被回收。
          2. 加载该类的ClassLoader已经被回收
          3. Class对象没有任何地方被引用,无法在任何地方通过反射访问该类

      1. 堆内存分代——有针对性的采⽤不同的回收机制,有利 于内存回收

        1.1. 年轻代和⽼年代      

          1. 年轻代对象朝生夕灭,

            一般划分是 一个Eden区和两个Survivor区。2. ⽼年代对象历久弥坚

        1.2. 创建对象时的分配

          1. 对象优先分配到Eden区,经历一定次数的回收之后,仍然存活的对象进⼊老年代。

          2. ⼤对象直接进⼊⽼年代

      2. 内存回收

          2.1. GC 分类 - 何时回收

            1. Minor GC 发生在新生代的内存回收

              当jvm无法为一个新的对象分配内存空间时会触发Minor GC,⽐如当Eden区满了,或者内存不连续。

            2. Full GC 发生在⽼年代的回收

              如果⽼年代没有⾜够空间,就会进行一次Full GC 对新生代和⽼年代都进行GC

          2.2. 哪些对象可以回收

            2.2.1. 引⽤用计数算法

              为对象添加引⽤用计数器,每个引⽤用计数+1,引⽤用失效,计数-1.会有循环引⽤用.

            2.2.2. 可达性分析

              通过一系列列的 GC Roots 对象作为起始点,搜索所⾛走过的路路径称为引⽤用链。

              当一个对象没被引⽤用的时候,就判定为可回收对象。

                GC Roots:

                  1. 虚拟机栈中引⽤用的对象
                  2. 方法区中类静态属性引⽤用的对象

                  3. 方法区中常量引⽤用的对象
                  4. 本地方法栈中引⽤用的对象

      3. 如何回收 - 回收算法介绍

        3.1 年年轻代回收算法

            3.1.1 标记-清除

              标记出所有需要回收的对象

              统一回收所有被标记的对象

              不⾜:

                效率,标记和回收的效率都不高

                空间,会产生大量的离散的内存碎片


            3.1.2 复制  

              空间换效率 新生代基本都采⽤用这种算法。

              将还存活的对象复制到另一块内存上,其他的一次性清理掉。Eden和2 个 Survivor

              HotSpot 默认是 8:1:1
              如果 10% 不够放置存活的对象,则直接进入老年代。


        3.2 ⽼年代算法

          3.2.1 标记-整理

            ⽼年代,一般就是对象存活率比较高。 ⽼而弥坚。

            与标记清理类似,但是不清理,而是让存活的对象移动到一端,

  • 相关阅读:
    cve-2015-1635 poc
    Python实现ORM
    Android完全退出应用的方法
    Java反射理解
    Android动画
    Android进程间通信IPC
    Java的四种引用方式
    Android底部菜单的实现
    Android中AsyncTask使用
    Android自定义控件
  • 原文地址:https://www.cnblogs.com/liuguobin/p/JVM.html
Copyright © 2011-2022 走看看