JVM入门篇

JVM入门篇

JVM结构图

类加载器

类加载过程

类加载器(ClassLoader)

  • 引导类加载器(BootstrapClassloader):用C++编写,是JVM自带的类加载器;负责加载Java的核心类库。(该加载器无法直接获取)

  • 扩展类加载器(ExtClassloader):负责加载/jre/lib/ext目录下的jar包

  • 应用程序类加载器(AppClassloader):负责加载java -classpath或-D java.class.path所指的目录下的类与jar包。(最常用的加载器)

双亲委派机制

当类加载器接收到类加载的请求时,他会将这个请求向上委托给父类加载器去完成,一直向上委托,直到顶层类加载器

顶层类加载器检查是否能够加载当前这个类,能加载就结束,使用当前加载器

否则就抛出异常,通知子加载器进行加载,都找不到则抛出Class Not Found 异常

Native 关键字

在有些类中,有些方法会携带native关键字,这个方法可以没有方法体,代表它是引用的。

凡是带了native关键字的,说明Java的作用范围达不到了,会回去调用底层C语言的库。

JNI(调用本地方法接口) 它的作用是扩展Java的使用,融合不同的编程语言为Java所用

Java在内存区域专门开辟了一块标记区域:Native Method Stack 本地方法栈 用来登记native方法,在最终执行的时候,通过JNI来加载本地方法库中的方法

方法区

Method Area 方法区 该区域属于共享区域,所有定义的方法信息都保存在该区域

方法区是被所有线程共享,所有字段、方法、字节码,以及一些特殊方法(构造函数等)也在此定义

注意的是:静态变量、常量、类信息(构造方法 接口定义) 运行时的常量池存在方法区中,但实例变量存在堆内存中,和方法区无关

PC寄存器

程序计数器 Program Counter Register

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

用来存储指向像一条指令的地址,也即将要执行的指令代码,在执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不记

栈(Stack)

先进后出 后进先出

栈的作用

栈内存,主管程序的运行,生命周期和线程同步

线程结束了,栈内存也就释放了,对于栈来说,不存在垃圾回收机制

栈存储的东西

八大基本类型、对象引用、实例的方法

程序正在执行的方法,一定在栈的顶部,方法执行结束后,弹栈,才到下一个栈执行,直到全部的栈执行完毕

待到main栈执行完毕,主程序也就执行完毕了

栈+堆+方法区的交互关系

三种JVM

  1. Sun公司的HotSpot。(java -version查看)

  2. BEA的JRockit

  3. IBM的J9VM

一个JVM只有一个堆内存,但是堆内存的空间大小是可以调节的

类加载器读取了类文件之后,一般会把类、方法、常量以及真正被引用的实例对象放入堆中

堆内存中细分为三个区域

  • 新生区(伊甸园区) new/young

  • 养老区 old

  • 永久区 Perm

GC垃圾回收机制

  • 轻GC

    • 伊甸园区无法容纳新生的对象时,就会触发一次轻GC(一般使用复制算法)。把伊甸园区和S0区中活跃的对象复制到S1区,并且清空伊甸园区和S0区,然后将S0区和S1区交换(谁空谁是to,也就是S0)

  • 重GC

    • 触发一次轻GC后,发现新生区还是无法存放新生的对象,就会尝试直接进入老年区,如果老年区也是放不下,就会触发一次重GC,清理老年区的空间,重GC之后,如果老年区还是放不下对象,就会报错误OOM(OutOfMenoryError)

GC垃圾回收机制,主要是在伊甸园区(轻GC)和老年区(重GC),且每次进行重GC之前,都会进行一次轻GC

如果新生区和老年区的内存都满了,堆内存不够,就会报错误OOM,java.lang.OutOfMenoryError:Java heap space

新生区

又叫伊甸园区,包括:伊甸园区,幸存0区,幸存1区

永久区

这个区域时常驻内存的,用来存放JDK自身携带的Class对象,Interface元数据,存储的时Java运行时的一些环境或类信息

这个区域不存在垃圾回收,关闭JVM虚拟机就会释放这个区域的内存

永久区什么时候会崩:

  • 一个启动类,加载了大量的第三方jar包

  • Tomcat部署了太多的应用

  • 大量动态生成的反射类,不断地被加载,知道内存满,就会出现OOM

永久代和元空间

就是方法区

方法区是一种规范,不同的虚拟机可以基于规范做出不同的实现,永久代和元空间就是出于不同jdk版本的实现

方法区就像一个接口,永久代和元空间是不同的两个实现类

只不过永久代是这个接口最初的实现类,后来这个接口一直进行变更,直到最后彻底废弃这个实现类,由新的实现类元空间进行替代

常量池

在jdk1.7之前,运行时常量池+字符串常量池是存放在方法区中的,HotSpot VM 对方法区的实现称为永久代

而在jdk1.7之后,字符串常量池从方法区移到堆中,运行时常量池保留在方法区中

在jdk1.8之后,HotStop移除永久代,使用元空间代替,此时字符串常量池保留在堆中,运行时常量池保留在方法区中,只是实现不一样了,JVM内存变成了直接内存

  • 19
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值