《别看了,你学不会的》——JVM(一)

JVM

JVM的基本结构

首先是一个Java文件通过Javac编译成class文件,然后经过Lorder进入到类加载子系统
类加载系统负责对类的加载,也包含着类加载的流程——加载,验证,准备,解析,初始化
目的就是将本地的或者网络上的字节码文件加载到JVM中,转化为Class信息
方法区,是一个规范,根据JDK的版本不同,又分为永久代和元空间,负责存储加载进来的类信息,所有线程都是共享的
Java堆,几乎所有的数组,对象,都是存放在堆中,公有的
直接内存,它的上限是基于服务内存

堆内存与直接内存的区别:堆内存需要申请,直接内存速度更快

方法区和堆是公有的;Java栈,本地方法栈和PC寄存器都是私有的

程序计数器

  1. 当前线程所执行的字节码的行号指示器,指向虚拟机字节码指令的位置
  2. 被分配了一块较小的内存空间
  3. 针对于非Native方法:是当前线程执行的字节码的行号指示器;针对于Native方法:则为undefined
  4. 每个线程都有自己独立的程序计数器,所以,该内存是线程私有
  5. 这块区域是唯一一个在虚拟机中没有规定任何OutOfMemeryError情况的区域

本地方法栈
native,栈都是跟方法相关的

虚拟机栈,栈
非native方法,也是最常用的方法
包含入参,出参,中间计算,方法异常……
栈帧,私有

垃圾回收器
回收垃圾

执行引擎
执行虚拟机加载进来的字节码
在这里插入图片描述

类加载在这里插入图片描述

加载

流。inputstream Resource
将class文件读取进来,读到的就是二进制的数据流
并将二进制流放入方法区中(永久代,元空间)

验证

验证加载进来的二进制数据流是不是合法的,合规的

准备

为类变量分配内存
为类变量分配初始值

解析

什么是符号引用,什么是直接引用
将符号引用转化成直接引用

初始化

类构造器< init >方法

符号引用和直接引用

Java -verbose
为什么会有符号引用?
因为在编译完java文件后,会生成一个class文件,此时JVM并不知道引用的内存地址,所以采用符号引用来表示类中内容的引用关系

虚拟机栈&本地方法栈
  • 虚拟机栈为执行Java方法服务,是描述方法执行的内存模型
  • 栈是线程私有的内存空间
  • 每次函数调用的数据都是通过栈传递的
  • 在栈中保存的内容为栈帧。它的数据结构就是先进后出。每当函数被调用,该函数就会被入栈,每当函数执行完毕,就会执行出栈操作。而当前栈顶,即为正在执行的函数
  • 每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、帧数据区、动态链接、方法出口等信息
  • 本地方法栈帧是为本地方法服务

栈帧

同一方法,提升最大栈空间
增加局部变量表对栈空间的占用

  • 运行时数据区,几乎所有的对象都保存在java堆中
  • java堆事完全自动化管理的,通过垃圾回收机制,垃圾对象会被自动清理,而不需要显式地释放
  • 堆是垃圾收集器进行GC的最重要的内存区域
  • Java堆可以分为:新生代(Eden区,S0区,S1区)和老年代
  • 在绝大多数情况下,对象首先分配在Eden区,在一次新生代GC回收后,如果对象还存活,则会进入S0或S1,之后,每经历过一次新生代回收,对象如果存活,它的年龄就会加1。当对象的年龄达到一定条件后,就会被认为是老年代对象,从而进入老年代
方法区
  • 逻辑上的东西,是JVM的规范,所有虚拟机必须遵守的
  • 是JVM所有线程共享的、用于存储类信息,例如:类的字段、方法数据、常量池
  • 方法区等大小决定了系统可以保存多少个类
  • JDK8之前——永久代
  • JDK8及以后——元空间
永久代
  • 指内存的永久保存区域,主要存放Class喝Meta(元数据)的信息,Class在被加载的时候被放入永久区域,它和存放实例的区域不同,GC不会在主程序运行期对永久区域进行清理。所以这也导致了永久代的区域会随着加载的Class的增多而胀满,最终抛出OOM异常
  • 如果系统使用了一些动态代理,那么有可能会在运行时生成大量的类,从而造成内存溢出。所以,设置合适的永久代大小,对于系统的稳定性是至关重要的
  • -XX:PermSize

设置初始永久代大小。例如:-XX:PermSize=5MB

  • -XX:MaxPermSize

设置最大永久代大小,默认情况下为64MB。例如: -XX:MaxPermSize=5MB

元空间
  • 在Java8中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代
  • 元空间的本质和永久代类似,元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用堆外的直接内存
  • 因此,与永久代不同,如果不指定大小,默认情况下,虚拟机会耗尽所有的可用系统内存
  • -XX:MaxMetaspaceSize

设置最大元数据空间。例如:-XX:MaxMetaspaceSize=20MB

为什么使用元空间替换永久代?

1.为永久代设置空间大小是很难确定的
2.对永久代进行调优是很困难的

JVM垃圾回收算法
什么是垃圾回收

GC:垃圾回收,Garbage Collection
垃圾:特指存在于内存中的、不会再被使用的对象
回收:清除内存中的“垃圾”对象

C++中,对象是由程序员创建的,也是由程序员销毁的,也就是说”对象的一生“都由程序员掌控,所以程序员既是权力最高的皇帝,也从事着最低层的工作
在Java中,程序员只负责创建对象,对象的销毁是由JVM控制的
可触及性
  • 什么是可触及性

就是GC时,是根据它来确定对象是否可被回收
也就是说,从根节点开始是否可以访问到某个对象,也说明这个对象是否被使用

  • 可触及性分为3种状态

可触及:从根节点开始,可以到达某个对象
可复活:对象引用被释放,但是可能在finalize()函数中被初始化复活
不可触及:由于finalize()只会执行一次,所以,错过这一次复活机会的对象,则为不可触及状态

四种引用级别
  • 强引用

就是一般程序中的引用,例如Student student = new Student();

  • 软引用

当堆空间不足时,才会被回收。因此,软引用对象不会引起内存溢出

  • 弱引用

当GC的时候,只要发现存在弱引用,无论系统堆空间是否不足,均会将其回收

  • 虚引用

如果对象持有虚引用,其实与没有引用是一样的。虚引用必须和引用队列在一起使用,它的作用是用于追踪GC回收过程,所以可以将一些资源释放操作放置在虚引用中执行和记录

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值