JVM虚拟机初步理解

1.JVM位置

Jdk包含jre+开发工具,jre包括了jvm+java标准类库。简单来说,jvm保证了Java的跨平台性,只要在不同的操作系统安装了jvm(Java虚拟机)就可以将java字节码(.java)编译成相同的字节码文件(.class)。jre(java runtime environment)负责运行java已编译程序所必须的软件环境,不能将java源代码编译成字节码文件。jdk可以创建、编译、运行java程序。

image.png

image.png

2.JVM的体系结构

image.png

3.类加载器

1.虚拟机自带的加载器
2.启动类(根)加载器Boot
3.扩展类加载器ExtClassLoader
4.应用程序加载器AppClassLoader


image.png

4.双亲委派机制

1.类加载器收到类加载的请求
2.将这个请求向上委托给父类加载器去完成,一直向上委托,直到启动类加载器
3.启动类加载器检查是否能够加载这个类,能加载就结束、否则抛出异常,通知子加载器进行加载
4.重复步骤3

5.沙箱安全机制

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


image.png

现在的安全模型就是,jvm给不同的代码分配不同的域,该代码就拥有这个域所拥有的对于本地资源的全部权限。(域类似于角色)
沙箱安全机制的组成部分:
1.字节码校验器:它保证java代码符合java语言规范,核心类由于已经校验过了封装好的,字节码不会校验核心类
2.类加载器,类加载器是利用了双亲委派机制,它保证了好的代码不会被坏的代码污染 它定义了被信任类库的边界 为代码归入域(类似于分配角色,分配权限)

6.Native

1.native:凡是带了native关键字的,说明如果Java的作用范围达不到了,会去调用底层C语言的库!
2.进入本地方法栈
3.调用本地方法本地接口 JNI
4.JNI作用:扩展Java的使用,融合不同的编程语言为java所用!(java诞生的时候C、C++横行,想要立足,必须要有调用C、C++的程序)
5.它在内存区域中专门开辟了一块标记区域:Native Method Stack中登记native方法
6.在最终执行的时候,加载本地方法库中的方法通过JNI

7.PC寄存器(程序计数器)

每个线程都有一个程序计数器,时线程私有的,就是一个指针,指向方法区中的方法字节码

8.方法区

方法区是被所有线程共享的,所有字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义,简单说,所有定义的方法的信息都保存在该区域,该区域属于共享区间。
静态变量、常量、类信息(构造方法、接口定义)、运行时常量池存在方法区中,但是实例变量存在堆内存中,和方法区无关。

9.栈

  • 栈内存,主管程序的运行,生命周期和线程同步
  • 线程结束,栈内存释放,对于栈来说,不存在垃圾回收的问题
  • 当前正在执行的方法永远在栈顶,方法执行完了就会被弹出栈
  • 栈里存放着:8大基本类型+对象引用+实例的方法
    栈运行原理:栈帧
    [图片上传中...(image.png-72806-1653390101960-0)]
    image.png

    栈溢出:StackOverflowError
    栈+堆+方法区的交互关系
    image.png

10.三种JVM

1.HotSpot
2.BEA JRockit
3.IBM J9 VM

11.堆

一个JVM只有一个堆内存,堆内存的大小是可以调节的。
堆内存中还要细分为三个区域:

  • 新生区(伊甸园区)
  • 养老区
  • 永久区
    image.png

    GC垃圾回收机制主要发生在伊甸园区和养老区,假设内存满了就会报OOM(堆内存满了)
    垃圾回收大致过程:
    1.所有的对象在伊甸园区诞生成长,之后会经历一次轻GC
    2.幸存下来的对象进入幸存区
    3.当幸存区满了之后,对象转移到养老区,并进行重GC
    在JDK8以后,永久存储区改为元空间

12.新生区,老年区、永久区

12.1新生区

-类诞生和成长的地方
-伊甸园,所有的对象都是在伊甸园中new出来的
-幸存区(0,1)


image.png

真理:经过研究,99%的对象都是临时对象

12.3永久区

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

  • jdk1.6之前:永久代,常量池在方法区中
  • jdk1.7:永久代,但是慢慢退化了,去永久代,常量池在堆中
  • jdk1.8之后:无永久代,常量池在元空间


    image.png

    注:这里的云空间只是逻辑上的存在,物理是不存在


    image.png

13.堆内存调优

OOM:
1.尝试扩大堆内存看结果(-Xms1024m -Xmx1024m -XX:+PrintGCDetails)
2.分析内存,看一下那个地方出现了问题(MAT,Jprofiler)

package com.jvm;

import java.util.Random;

/**
 * @author:wangjie
 * @create:2022-05-25 18:15
 * @Description:模拟堆满了java.lang.OutOfMemoryError: Java heap space
 */
public class OOM {
//    -Xms8m -Xmx8m -XX:+PrintGCDetails 设置运行时初始内存分配大小默认1/64,最大分配内存大小1/4,打印GC垃圾回收机制详细信息
    //-Xms8m -Xmx8m -XX:+HeadDumpOnOutOfMemoryError 如果发生OutOfMemoryError错误就将信息dump下来分析
    public static void main(String[] args) {
        String str = "wangjie";
        while (true){
            str+=str+new Random().nextInt(1111111111)+new Random(222222222);
        }
    }
}

14.GC(垃圾回收机制)

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

  • 新生代
  • 幸存区(from,to)
  • 老年区
    GC两种类:轻GC、重GC
    GC题目:
  • JVM的内存模型和分区 详细到每个区放什么?
  • 堆里面的分区有哪些?Eden、from、to,老年区,说说他们的特点
  • GC的算法有哪些?标记清除法、标记压缩、复制算法、引用计数器

14.1常用算法

14.1.1引用计数法

image.png

14.2复制算法

image.png

image.png
  • 好处:没有多余的内存碎片
  • 坏处:浪费了一个内存空间(to区总是空的)
    复制算法最佳使用场景:对象存活时间较低

14.3标记清除法

image.png
  • 好处:不需要额外空间
  • 坏处:两次扫描,严重浪费时间,会产生内存碎片
    标记清除压缩算法
    image.png

    image.png

    image.png

15.JMM

Java 内存模型
作用:缓冲一致性协议,用于定义数据读写的规则
JVM定义了线程工作内存和主内存之间的抽象关系:线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存。
解决共享对象可见性:validate


image.png

16.对象创建过程

1.类加载检查
检查这条new指令的参数是否能在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否被加载过、解析、和初始化过,如果没有,就要先执行类加载过程。
2.分配内存
在类加载检查通过之后,虚拟机为新生对象分配内存,分配内存的方式有两种,指针碰撞(规整情况)和空闲列表(不规整情况),选择那种分配方式由java堆的内存是否规整决定,而java堆是否规整又由垃圾回收算法决定。
3.初始化零值
内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头),这一步操作保证了对象的实例字段在 Java 代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值。
4.设置对象头
初始化零值完成之后,虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的 GC 分代年龄等信息。 这些信息存放在对象头中。 另外,根据虚拟机当前运行状态的不同,如是否启用偏向锁等,对象头会有不同的设置方式。
5.执行init方法
在上面工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了,但从 Java 程序的视角来看,对象创建才刚开始,<init> 方法还没有执行,所有的字段都还为零。所以一般来说,执行 new 指令之后会接着执行 <init> 方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全产生出来。

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

推荐阅读更多精彩内容