JVM

JVM
基本样子
在这里插入图片描述

执行流程
双亲委派机制
类加载器收到加载请求不会自己去执行而是从下面往上面把请求委派给父类,直到BOOT启动类加载器,如果启动类加载器加载不了,就会往下尝试执行加载。
APP–>EXC–>BOOT 都是加载器
向上查找,向下执行
在这里插入图片描述

启动类加载器(Bootstrap ClassLoader):前面已经大致介绍过了,这个类加载器负责将存放在 <JRE_HOME>\lib 目录中的,或者被 -Xbootclasspath 参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如 rt.jar,名字不符合的类库即使放在 lib 目录中也不会被加载)类库加载到虚拟机内存中。启动类加载器无法被 Java 程序直接引用,用户在编写自定义类加载器时,如果需要把加载请求委派给启动类加载器,直接使用 null 代替即可。
扩展类加载器(Extension ClassLoader):这个类加载器是由 ExtClassLoader(sun.misc.Launcher E x t C l a s s L o a d e r ) 实 现 的 。 它 负 责 将 < J A V A H O M E > / l i b / e x t 或 者 被 j a v a . e x t . d i r 系 统 变 量 所 指 定 路 径 中 的 所 有 类 库 加 载 到 内 存 中 , 开 发 者 可 以 直 接 使 用 扩 展 类 加 载 器 。 应 用 程 序 类 加 载 器 ( A p p l i c a t i o n C l a s s L o a d e r ) : 这 个 类 加 载 器 是 由 A p p C l a s s L o a d e r ( s u n . m i s c . L a u n c h e r ExtClassLoader)实现的。它负责将 <JAVA_HOME>/lib/ext 或者被 java.ext.dir 系统变量所指定路径中的所有类库加载到内存中,开发者可以直接使用扩展类加载器。 应用程序类加载器(Application ClassLoader):这个类加载器是由 AppClassLoader(sun.misc.Launcher ExtClassLoader<JAVAHOME>/lib/extjava.ext.dir使ApplicationClassLoaderAppClassLoadersun.misc.LauncherAppClassLoader)实现的。由于这个类加载器是 ClassLoader 中的 getSystemClassLoader() 方法的返回值,因此一般称为系统类加载器。它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。

1.类伴随它的类加载器一起具备了一种带有优先级的层次关系,确保了在各种加载环境的加载顺序。

2.保证了运行的安全性,防止不可信类扮演可信任的类

例:类java.lang.Object,它由启动类加载器加载,双亲委派模型保证任何类加载器收到的都是对java.lang.Object的加载请求,最终通过这个模型把它委托给处于Bootstrap(最顶端的启动类加载器)进行加载,保证了Object类在程序的各个类加载器环境中都是同一个类。相反:如果没有双亲委派模型,由各个类加载器自行去加载的话,如果用户自己编写了一个成为java.lang.Object的类,并用自定义的类加载器去加载,那么系统中会出现多个不同的Object类,Java类型体系中最基础的行为也就无法保证,应用程序也将会变得一片混乱。

类在JVM中加载的规则,任何一个类只需要在JVM中加载一次,不需要重复加载,对象可以有n个,但是对象的模板类只需要有一个(只需要一个模板即可以加载无数对象),可以节省内存的空间。

加载一个类的时候,首先从自定义加载器开始查找,看它有没有加载过这个类,如果加载过,则直接返回,如果没有加载,怎么办?就委派给AppClassLoader去加载。

开始查找AppClassLoader有没有加载过这个类,如果加载过,则直接返回,否则委派给ExtClassLoader去加载,再重复上述过程直到BootstrapClassLoader(顶层的启动类记载器),如果加载过,直接返回,如果此时还是没加载过,就会逆向加载,将整个过程反过来

BootstrapClassLoader–>ExtClassLoader–>AppClassLoader–>自定义ClassLoader
完整过程走下来如果还是没有加载到,就会抛出ClassNotFoundException。

栈是目录,堆是内容

Native关键字
带native关键字的去调用了本地方法接口JNI(扩展java的使用,融合各种语言的使用)
开辟了一块标记区域:Native method stack登记native方法
最后执行的时候,加载本地方法库中的方法通过JNI

静态变量,常量,类的信息(构造函数,接口信息),运行时的常量池也放在方法区里。实例变量放在堆中

内存中对象实例的过程
在这里插入图片描述
GC的作用区域就是堆heap和方法区

public class demo2 {
// 获得oomdump文件 -Xms8m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError
//Java dump快照文件
//xms初始化内存分配大小 1/64
//xmx最大内存分配 1/4
//-XX:GCDetails GC清理信息
//-XX:+HeapDumpOnOutOfMemoryError 生成oom(栈溢出)dump文件快照

byte[] array=new byte[1*1024*1024];
public static void main(String[] args) {
    ArrayList<demo2> s = new ArrayList<>();
    int count=0;
    try {
        while (true){
            s.add(new demo2());
            count++;
        }
    }
    catch (Error e){
        System.out.println("Count"+count);
        e.printStackTrace();
    }
}

新生代:Eden区 幸存者from survivor1区 to survivor2区
老年代:年龄大于15 (次gc)或者幸存者区的同年龄的加起来大于jvm内存一半的进入。-XX: -XX:maxtunuringthreshold设置进入老年代的时间
谁空谁是to区 因为有空间可以去 from a to b

老年代满了进行重gc full gc 全局gc所有的
新生代满了进行轻gc mirror gc

GC四大算法 复制算法 标记整理算法 标记清除算法,分代收集算法 (引用计数法)
年轻代主要使用的复制算法from to from区 与to区之间互相复制转换
在这里插入图片描述
好处没有内存碎片 但是永远多了一片空空间 浪费


标记算法 对没有标记的对象清除 先标记再清除
优点不需要额外的空间
缺点 两次扫描,浪费时间,产生内存碎片


标记压缩算法(优化标记)
扫描向一端移动存活的对象 连续的内存碎片就不是垃圾了

一般是混合使用标记清除和标记压缩

没有最优算法 只有最合适算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值