浅谈JVM

JAVA程序运行过程

在这里插入图片描述
.java文件—编译器编译–>.class文件–类加载器–>加载进内存JVM中–加载进–>操作系统。
这下我们就知道JVM在什么地方可以用到。

JVM几大板块

1类加载器

两种类型的类加载器
1.JAVA虚拟机自带的加载器
根类加载器(BootStrap)(BootClassLoader) sun.boot.class.path (加载系统的包,包含jdk核
心库里的类)
扩展类加载器(Extension)(ExtClassLoader) java.ext.dirs(加载扩展jar包中的类)
系统(应用)类加载器(System)(AppClassLoader) java.class.path(加载你编写的类,编译后
的类)
2。用户自定义的类加载器
Java.long.ClassLoader的子类(继承),用户可以定制类的加载方式
双亲委派机制
原理:
1.首先类加载收到请求
2.把这个请求交给启动类加载器去完成,如果完成则加载否则交给标准拓展类加载器加载,如果完成则加载否则交给应用程序加载器。再找不到则抛出异常。
代码测试:

package java.lang;
public class String {
public static void main(String[] args) {
System.out.println(1);
}
}

在这里插入图片描述
大家所知道的String类,在默认情况下是在启动类加载器进行加载的,假设自己定义一个String类,也可以编译但是无法被加载运行,就是这个原理。
双亲委派机制是为了保护JAVA核心类库所提供的类,不会被自定义的替换。

2Native关键字

反是带了native关键字的,说明Java的作用范围达不到,去调用的是底层C语言的库。
JNI:Java Native Interface (Java本地方法接口)
凡是带了Native关键字的方法就会进入本地方法栈;
Native Method Stack 本地方法栈。

3方法区

Method Area 方法区 是 Java虚拟机规范 中定义的运行时数据区域之一,它与堆(heap)一样在线程之间
共享。

Java 虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做 Non-Heap(非堆),目
的应该是与 Java 堆区分开来。
运行时常量池(Runtime Constant Pool)是方法区的一部分。Class 文件中除了有类的版本/字段/方法/接口等描述信息外,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用,这部分内容将类在加载后进入方法区的运行时常量池中存放。运行期间也可能将新的常量放入池中,这种特性被开发人员利用得比较多的是 String.intern() 方法。受方法区内存的限制,当常量池无法再申请到内存时会抛出 OutOfMemoryError 异常。

4栈

栈:后i进先出/先进后出
队列:先进先出(FIFO : First Input First Output)
栈管理程序运行
存储一些基本的类型值,对象的引用,方法等。
栈的优势是,存取速度比堆快,仅次于寄存器,并且栈数据可以共享。
1、栈也叫栈内存,主管Java程序的运行,是在线程创建时创建,它的生命期是跟随线程的生命期,线程
结束栈内存也就释放。
2、对于栈来说不存在垃圾回收问题,只要线程一旦结束,该栈就Over,生命周期和线程一致,是线程
私有的。
3、方法自己调自己就会导致栈溢出(递归死循环测试)

5堆

一个JVM只有一个堆内存。堆内存的大小是可以调节的。
类加载器读取了类文件后,一般会把什么东西东西放到堆中?(类,方法,常量,变量,保存我们所有
引用类型的真是对象)

  1. 新生区
  2. 老年区
  3. 永久区
    在这里插入图片描述
    GC垃圾回收。主要是在伊甸园区和养老区~
    假设内存满了(OOM),堆内存不够!java.lang.OutOfMemoryError:Java heap space
    在JDK以后,永久存储区改了名字(元空间)
    新生区
    类诞生和成长的地方,甚至死亡
    伊甸园区:所有的伊甸园区new出来的
    幸存者区(0,1)
    老年区
    新生区存活下来的进去老年区
    永久区
    这个区域常驻内存的,用来存放JDK自身携带的Class对象。
    包括Interface元数据,存储的是Java运行时的一些环境或类信息~,这个区域已存在垃圾回收!关闭虚
    拟机就会释放这个区域的内存~
    一个启动类,加载了大量的第三方jar包。Tomcat部署了太多的应用,大量的动态生成的反射类,不断
    地被加载,知道内存满,就会出现OOM;
    JDK1.6之前: 叫做永久代,常量池在方法区
    JDK1.7 :叫做永久代,但是慢慢的退化了, 去掉永久代 ,常量池在堆中
    JDK1.8之后 :无永久代,常量池在元空间1.13、堆内存调优
    在这里插入图片描述

垃圾回收机制

1什么是垃圾

一系列GcRoots对象作为起点,进行向下搜索时无法达到的对象被称之为垃圾对象
在这里插入图片描述
Java中可以作为 GC Roots的对象:(共4种)
1、虚拟机栈(栈帧中的局部变量表)中引用的对象;
2、方法区中的类静态属性引用的对象。
3、方法区中常量引用的对象。
4、本地方法栈中 JNI (Native方法)引用的对象。

2复制算法

复制算法:伊甸园区产生的垃圾会到幸存区from,如果幸存区from和伊甸园区都满了会经历一次轻gc,清理掉不可达对象,并将可达对象复制到幸存区to里面,并且清理掉伊甸园区和幸存区from里面的可达对象,再将幸存区from和幸存区to进行交换,保证幸存区to始终为空。并将这些可达的存活对象年龄设置为1,当经历15次(默认值,可更改)轻GC后,会将依旧存活的对象放入老年代。

缺点:占用内存空间,因为幸存区to永远是空着的。
优点:不会产生内存碎片。
我们为什么会在新生区使用复制算法?
因为在新生区会有很多对象被清理掉,对象存活率低,这种情况复制算法的回收整理,速度是最快的。复制算法的效率只和当前存活对象大小有关,因而很适用于年轻代回收。

3标记清除算法

当堆内存空间耗尽就会进行标记清除算法
第一步对存活对象进行标记,实际就是遍历所有GcRoots的可到达对象,标记为存活对象
第二步遍历整个堆,对没有标记的对象进行清理。
用通俗的话解释一下 标记/清除算法,就是当程序运行期间,若可以使用的内存被耗尽的时候,GC线程
就会被触发并将程序暂停,随后将依旧存活的对象标记一遍,最终再将堆中所有没被标记的对象全部清
除掉,接下来便让程序恢复运行。
缺点:这个算法需要暂停整个应用,会产生内存碎片。
优点:不占用内存空间。

标记清除压缩算法

在标记清楚的基础上再进行压缩,即是首先对可达到对象进行标记,第二部将所有存活的对象统一都向一段进行移动,直接清除边界以外的内存,标记的对象会被整理到一起,而标记以外的对象会被清理掉。
优点:标记、整理算法不仅可以弥补 标记、清除算法当中,内存区域分散的缺点,也消除了复制算法当中,内
存减半的高额代价;
缺点:时间复杂度高。

由于老年代对象存活率高,需要清理的对象不多,故产生的内存碎片不会太多故采用标记压缩清除算法和标记清除算法相结合。

算法比较

内存效率:复制算法 > 标记清除算法 > 标记整理算法 (时间复杂度)
内存整齐度:复制算法 = 标记整理算法 > 标记清除算法
内存利用率:标记整理算法 = 标记清除算法 > 复制算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值