JVM学习记录

  • 数据是商品,硬盘是仓库,内存是货架,买东西是只能在货架上买的

  • 货架容纳不下当前需要摆放的商品,即内存溢出

  • JVM 虚拟出一个计算机来仿真模仿各种计算机功能

  • JVM 有自己的硬件架构,如处理器、堆栈、寄存器等,还有对应分指令系统

  • JVM是淘宝店铺,不是真是存在的货架但能上架下架商品,数量也是有限

  • 平台无关性可以理解成异地购物

  • 内存模型就是具体的各变量访问规则

  • 所有变量保存主内存,每条线程有自己的工作内存保存用到变量的内存副本

  • 不能直接读写内存的变量

  • 不同线程无法访问对方的工作内存变量,值传递要通过主内存进行

  • 执行引擎相当于CPU

  • 8种操作完成主内存与工作内存的交互协议

  • lock锁定变量,将其变成一条线程独占

  • unlock 解锁

  • read 将主内存变量传输到线程的工作内存 -> load 将取得变量放入变量副本

    主内存->read->load->工作内存

  • write 将store得到的变量副本写入到主内存

    工作内存->store->write->主内存

  • use 将工作内存的变量传递给执行引擎

    工作内存->use->执行引擎

  • assign 将执行引擎收到的值赋给工作内存

    执行引擎->assign->工作内存

  • store 将工作内存的变量传送到主内存供write使用

  • JVM内存划分:线程私有,线程共享

  • 共享:方法区,堆

  • 私有:虚拟机栈,程序计数器,本地方法栈

  • 局部变量表会随着函数栈帧的销毁而销毁,包括基本数据类型、对象引用、字节码指令地址

  • 操作栈保存计算过程的中间结果

  • 每个栈帧包含一个指向运行时常量池中该帧所属方法引用,持有该引用是为了动态连接

  • 正常完成出口,异常完成出口,无论哪种形式推出,都需要返回到方法被调用位置

程序计数器

  • 程序计数器是一块较小的内存空间,可以看作是当前线程执行的字节码的行号指示器。

  • 为了线程切换后能恢复到正确的执行位置,每条线程都有一个私有的计数器。

  • 程序计数器是唯一一个在 Java 虚拟机规范中没有规定任何 OOM 情况的区域。

    虚拟机栈

  • 虚拟机栈就是Java方法栈,每个方法执行时创建一个栈帧(Stack Frame),栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息,生命周期与线程相同。

  • 虚拟机栈的两种异常:StackOverflowError(栈请求深度大于规定的最大深度),OutOfMemoryError(扩展申请不到足够的内存)

本地方法栈(Nativie Method Stack)

  • Native方法服务
  • 虚拟机栈一样的异常

Java堆

  • 存放创建的对象实例 即是所有的变量
  • 最大的内存区域
  • 虚拟机创建时创建
  • GC管理的主要区域

方法区

  • 线程共享
  • 已被虚拟机加载的数据
  • 存储类型:类信息 常量 静态变量 即时编译器编译后的代码
  • 此区大小决定可以保存多少个类,定义过多溢出,会抛出OutOfMemoryError
  • 分运行时常量池和直接内存
  • Class 文件中除了有类的版本、字段、方法和接口等描述信息,还有一项信息就是常量池(Constant Pool Table)。 常量池->运行时常量池
  • 直接内存
  • 直接内存的分配不会受到 Java 堆大小的限制,但是会受到设备总内存(RAM 以及 SWAP 区)大小以及处理器寻址空间的限制。
  • 通过一个存储在 Java 堆中的 DirectByteBuffer 对象作为这块内存的引用进行操作,这样能避免在 Java 堆和 Native 堆中来回复制数据。
  • 默认容量与Java堆最大值一样

栈帧

  • 方法的调用链路由Java一个个方法栈帧组成
  • 一个栈帧包括了局部变量表、操作栈、动态连接、返回地址
  • 局部变量表中的数据在函数调用结束后随着栈帧的销毁而销毁
  • 操作数栈保存计算过程的中间结果,临时变量存储的地方
  • 动态连接指执行运行时常量池中该栈帧所属方法引用
  • 返回地址:正常完成出口,异常完成出口,无论是哪种推出方式,都要返回到方法被调用位置,才能继续执行

可达性算法

  • 在主流的商用程序语言(Java、C# 和 Lisp 等)的主流实现中,都是通过可达性分析(Reachability Analysis)判定对象是否存活的。
  • 当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是不可用的。

引用相关

  • 在 JDK 1.2 之后,Java 对引用的概念进行了扩充,将引用分为强引用、软引用、弱引用和虚引用四种,这四种引用强度按顺序依次减弱。

  • 强引用是指代码中普遍存在的,比如 "Object obj = new Object()" 这类引用。直接访问,不会回收(即使OOM),可能内存泄漏

  • 对于软引用关联的对象,在系统即将发生内存溢出前,会把这些对象列入回收范围中进行二次回收。如果二次回收后还没有足够的内存,就会抛出内存溢出异常。在 JDK 1.2 后,Java 提供了 SoftReference 类来实现软引用。(这个特性很适合用来实现缓存:比如网页缓存、图片缓存等。)

    SoftReference<String> sr = new SoftReference<String>(new String("hello"));
    
  • 弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。(biss)如果存在强引用同时与之关联,则进行垃圾回收时也不会回收该对象

    WeakReference<String> sr = new WeakReference<String>(new String("hello"));
    
  • 虚引用在java中用java.lang.ref.PhantomReference类表示。

  • 虚引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之 关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。

  • 当我们操作不当导致某块内存泄漏时,GC 就不能对这块内存进行回收。

  • 拿 Android 来说,进行 GC 时,所有线程都要暂停,包括主线程,16ms 是 Android 要求的每帧绘制时间,而当 GC 的时间超过 16ms,就会造成丢帧的情况,也就是界面卡顿。

垃圾回收算法

  • 标记-清除算法(Mark-Sweep) 标记所有商品的状态没人买的就下架 :效率低,标记和清除的效率都不高;内存碎片太多会导致当程序需要分配较大的对象时,无法找到足够的连续内存而不得不提前触发 GC

  • 复制(Copying)收集算法 可用内存按容量划分为大小相等的两块,这块内存用完了,就把存活的对象复制到另一块内存上,然后把已使用的空间一次清理。:每次都是对半个内存区域进行回收,内存分配时也不用考虑内存碎片等复杂问题。

  • 浪费空间

    把内存缩小一半来使用太浪费空间。

  • 有时效率较低

    在对象存活率高时,要进行较多的复制操作,这时效率就变低了

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,576评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,515评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,017评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,626评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,625评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,255评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,825评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,729评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,271评论 1 320
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,363评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,498评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,183评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,867评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,338评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,458评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,906评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,507评论 2 359

推荐阅读更多精彩内容

  • 第二部分 自动内存管理机制 第二章 java内存异常与内存溢出异常 运行数据区域 程序计数器:当前线程所执行的字节...
    小明oh阅读 1,174评论 0 2
  • 第6章类文件结构 6.1 概述 6.2 无关性基石 6.3 Class类文件的结构 java虚拟机不和包括java...
    kennethan阅读 938评论 0 2
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,111评论 1 32
  • 这篇文章是我之前翻阅了不少的书籍以及从网络上收集的一些资料的整理,因此不免有一些不准确的地方,同时不同JDK版本的...
    高广超阅读 15,628评论 3 83
  • 一、运行时数据区域 Java虚拟机管理的内存包括几个运行时数据内存:方法区、虚拟机栈、本地方法栈、堆、程序计数器,...
    luhanlin阅读 546评论 0 0