解析 虚拟机将常量池内的符号引用替换为直接引用的过程。...解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符 7 类符号引用进行 初始化 到初始化阶段,才真正开始执行类中定义的 Java 程序代码,此阶段是执行 ...对应场景是:使用 new 实例化对象、读取或设置一个类的静态字段(被 final 修饰、已在编译期把结果放入常量池的静态字段除外)、以及调用一个类的静态方法。...对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。 当初始化类的父类还没有进行过初始化,则需要先触发其父类的初始化。...将 class 文件二进制数据放入方法区内,然后在堆内(heap)创建一个 java.lang.Class 对象,Class 对象封装了类在方法区内的数据结构,并且向开发者提供了访问方法区内的数据结构的接口
软引用 这种引用的功能即是前言部分提到的:如果某个 Java 对象只被软引用所指向,那么在 JVM 要新建一个对象的时候,如果当前虚拟机所剩下的堆内存不足以保存这个要新建的对象的时候(即虚拟机将要抛出...GC 调用, * 之后,通过该引用对象的 get 方法得到的返回值为 null, 该方法不应该被程序员主动调用 */ public void clear() {...* 如果构造该引用对象时没有指定对应的引用队列,那么该方法始终返回 false */ public boolean isEnqueued() { return (this.queue...GC 回收之后会由 GC 调用这个方法, * 代表将该引用进入对应的引用队列(即该引用指向的对象被回收) */ public boolean enqueue() {...ReferenceQueue.NULL : queue; } } 我们在 Reference 类中的 enqueue 方法(这个方法本身会被 GC 线程调用)中发现其直接调用了对应引用队列(ReferenceQueue
之后可以通过调用Buffer.reset()方法恢复到这个position。方便数据的重新读取,而流只能是单向读取。...虚拟机会定期对垃圾内存进行回收,在某些特定的时间点,它会进行一次彻底的回收(full gc)。...堆外内存有以下特点: 对于大内存有良好的伸缩性 对垃圾回收停顿的改善可以明显感觉到 在进程间可以共享,减少虚拟机间的复制 接下来看一下DirectByteBuffer的实现: DirectByteBuffer...但是调用System.gc()并不能够保证full gc马上就能被执行。所以在后面打代码中,会进行最多9次尝试,看是否有足够的可用堆外内存来分配堆外内存。...);)说到PhantomReference它其实主要是用来跟踪对象何时被回收的,它不能影响gc决策,但是gc过程中如果发现某个对象除了只有PhantomReference引用它之外,并没有其他的地方引用它了
综上,我们可以知道:官方文档对boolean类型没有给出精确的定义,《Java虚拟机规范》给出了“单独时使用4个字节,boolean数组时1个字节”的定义,具体还要看虚拟机实现是否按照规范来,所以1个字节...“==”判断的是两个对象的内存地址是否一样,适用于原始数据类型和枚举类型(它们的变量存储的是值本身,而引用类型变量存储的是引用);equals是Object类的方法,Object对它的实现是比较内存地址...Java中多态的实现原理 所谓多态,指的就是父类引用指向子类对象,调用方法时会调用子类的实现而不是父类的实现。多态的实现的关键在于“动态绑定”。...详细介绍请戳 Java动态绑定的内部实现机制 简述Java中创建新线程的两种方法 继承Thread类(假设子类为MyThread),并重写run()方法,然后new一个MyThread对象并对其调用start...创建了线程池对象后,我们就可以调用submit方法提交任务到线程池中去执行了;线程池使用完毕后我们要记得调用shutdown方法来关闭它。
解析 解析阶段是指虚拟机将常量池中的符号引用替换为直接引用的过程。...下面我们解释一下符号引用和直接引用的概念: 符号引用与虚拟机实现的布局无关,引用的目标并不一定要已经加载到内存中。...虚拟机会保证方法执行之前,父类的方法已经执行完毕。p.s: 如果一个类中没有对静态变量赋值也没有静态语句块,那么编译器可以不为这个类生成()方法。...常量在编译期间会存入调用类的常量池中,本质上并没有直接引用定义常量的类,不会触发定义常量所在的类。 通过类名获取Class对象,不会触发类的初始化。...ClassLoader.loadClass(className)方法,内部实际调用的方法是 ClassLoader.loadClass(className,false); 第2个 boolean参数
当调用发不正确的调用方法时,抛出该异常 IllegalMonitorStateException 抛出此异常表示线程已尝试在对象的监视器上等待,或者在没有指定监视器的情况下通知在对象监视器上等待的其他线程...如果Java虚拟机或ClassLoader实例尝试加载类的定义(作为普通方法调用的一部分或作为使用new表达式创建新实例的new ),则new该类,并且无法找到该类的定义。...NoSuchMethodException 无法找到特定方法时抛出 NullPointerException 当应用程序在以下情况尝试使用null时抛出。 这些包括: 调用null对象的实例方法。...访问或修改null对象的字段。 将null的长度视为数组。 访问或修改值为null的元素。...Void Void类是一个不可实例化的占位符类,用于保存对表示Java关键字void的类对象的引用
,从字面知道,这里添加了一个GC的watcher,里面的线程运行条件是当虚拟机内存占用超过虚拟机分配的最大内存的3/4时,对一些Activity进行释放。...也就是说当执行到GC的时候,会调用到这里,然后执行Runnable的时候调用到虚拟机3/4内存的计算。 finallize方法最后重新创建了一个GcWatcher的弱引用。...sGcWatcher是一个静态对象,如果它是一个强引用,那么他就会存在静态引用方法区,就会导致这个强引用的GC线程无法回收。...所以作为弱引用,引用对象在被回收时就会触发sGcWatcher的finalize方法,执行结束时仔new一个弱引用出来,以保证下次的调用。 那么这里如何保证GC回收呢?...回到addGcWatcher,里面的线程运行条件是当虚拟机内存占用超过虚拟机分配的最大内存的3/4时,就会触发GC,对一些Activity进行释放。
前提 这篇文章主要基于JDK11的源码和最近翻看的《深入理解Java虚拟机-2nd》一书的部分内容,对JDK11中的Reference(引用)做一些总结。...实例调用 boolean enqueue(Reference对象"有机会"被判定为可以回收的对象。 ? 在Java语言中,可以作为GC根集的对象包括下面几种: 虚拟机栈(栈帧中的本地变量表)中引用的对象。...JVM会把以下两种情况认为对象没有必要执行finalize()方法: 对象没有覆盖继承自Object类的finalize()方法。 对象的finalize()方法已经被JVM调用过。...这里之所以叫尝试执行是因为JVM会保证触发满足条件的对象的finalize()方法,但是并不承诺会等待它执行结束,这是因为:如果一个对象在执行finalize()方法耗时较长,甚至发生了死循环,将会导致
()方法是编译器收集代码中的静态变量(非final修饰)和静态代码块后生成的方法,它的主要作用是在类加载过程中的初始化阶段被调用,用于对静态变量进行赋值以及一些其他的初始化操作(这些操作可能写在静态代码块中...不同于类的构造方法,类的构造方法在字节码层面是()方法,()方法无需显式调用父类的()方法,虚拟机会保证在子类的()方法,父类的对类的主动引用,除此之外的场景,都不会去触发类的初始化,这些场景的行为称之为对类的被动引用。...loadClass(String name, boolean resolve)是loadClass(String name)重载方法,参数boolean resolve代表是否生成Class对象的同时进行解析相关操作...去加载,也就是使用这个findBootstrapClassOrNull(name);方法去加载类,如果父类加载器加载失败,也就是加载的结果是class对象为null,那么将调用子类加载器的findClass
Java 虚拟机为 每个类 都准备了一张 方法表来存放类中所有的方法 。 当需要调用一个类的方法的时候,只要知道这个方法在 方法表中的偏移量 就可以直接调用该方法了。...通过 解析操作符号引用 就可以直接转变为 目标方法在类中方法表的位置 ,从而使得方法可以被调用。...所以,解析阶段是虚拟机将常量池内的 符号引用替换为直接引用的过程 ,也就是得到 类或者字段、方法在内存中的指针或者偏移量 。...即程序 **调用类的静态方法** 。对类进行 反射调用 时,如果类没初始化,需要触发其初始化。 初始化一个类,如果其 父类还未初始化 ,则先 触发该父类的初始化 。...需要注意的是,Java虚拟机对Class文件采用的是 按需加载 的方式,也就是说当需要使用该类时才会将它的Class文件加载到内存生成Class对象。 每一个类都有一个对应它的类加载器。
类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口 在加载阶段,虚拟机需要完成以下3件事情: 通过一个类的全限定名来获取定义此类的二进制字节流...二进制字节流就按照虚拟机所需的格式存储在方法区之中, 而且在Java堆中也创建一个java.lang.Class类的对象,这样便可以通过该对象访问方法区中的这些数据 加载时机 当应用程序启动的时候,所有的类不会被一次性加载...解析:虚拟机将常量池中的符号引用替换为直接引用(内存地址)的过程 解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符...init: 在实例创建出来的时候调用,也就是构造函数,包括: new操作符 普通代码块 调用Class或java.lang.reflect.Constructor对象的newInstance()方法;...调用任何现有对象的clone()方法; 通过java.io.ObjectInputStream类的getObject()方法反序列化。
init:null teach: Student learn 可以看到,在构造器执行的时候未完成属性的注入,而在调用方法的时候已经完成了注入。...它的大致过程是这样的: 白话: 首先A对象实例化,然后对属性进行注入,发现依赖B对象 B对象此时还没创建出来,所以转头去实例化B对象 B对象实例化之后,发现需要依赖A对象,那A对象已经实例化了,所以B对象最终能完成创建...---- 这里其实就是主干逻辑,在整个过程中会调用三次doGetBean()方法 第一次调用的时候会尝试获取A对象实例,此时走的是第一个getSingleton()方法,由于没有已经创建的A对象的成品或半成品...,因而这里得到的是null 然后就会调用第二个getSingleton()方法,创建A对象的实例,然后递归的调用doGetBean()方法,尝试获取B对象的实例以注入到A对象中 此时由于Spring容器中也没有...B对象的成品或半成品,因而还是会走到第二个getSingleton()方法,在该方法中创建B对象的实例 创建完成之后,尝试获取其所依赖的A的实例作为其属性,因而还是会递归的调用doGetBean()方法
每个Class对象包含了一个定义它的ClassLoader的引用(『Class#getClassLoader()』返回一个指向ClassLoader的引用)。...这个新定义的类的实例能使用『Class#newInstance』方法来创建。 通过一个类加载器创建的对象的方法和构造方法可能会引用到其他类。...为了确定所引用的类,Java虚拟机调用最初创建该类的类加载器的『loadClass』方法。...如果父类加载器是null,那么虚拟机内建的类加载器(bootstrap class loader)会被使用。 ③ 调用『findClass(String)』方法来寻找类。...如果类在上述步骤中被找到了,并且“解析”标志位true,那么这个方法接下来会在结果类对象上调用『resolveClass(Class)』。
不同的虚拟机对类验证的实现可能会有所不同,但大致都会完成以下四个阶段的验证:文件格式的验证、元数据的验证、字节码验证和符号引用验证。...使用 Java.lang.refect 包的方法对类进行反射调用时,如果类还没有进行过初始化,则需要先触发其初始化。...虚拟机规定只有这四种情况才会触发类的初始化,称为对一个类进行主动引用,除此之外所有引用类的方式都不会触发其初始化,称为被动引用。...六,反射 JAVA反射机制: 在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java...c, obj.getClass();所有Java对象都具备这个方法,该方法用于返回调用该方法的对象的所属类关联的Class对象 2、获取构造方法 Class类提供了四个public方法,用于获取某个类的构造方法
方法是由编译器自动收集类中的变量赋值操作,静态语句块中的语句 合并而成的 虚拟机会保证 子方法执行之前它的父类方法已经执行完毕 如果一个类中没有对静态变量赋值...定义对象数组,不会触发该类的初始化 常量在编译期间会存入调用类的常量池中,本质上并没有直接引用定义常量的类,不会触 发定义常量所在的类 通过类名获取 Class 对象,不会触发类的初始化。...new一个对象的时候 访问类的静态变量(注意上面的,如果是访问父类的静态字段,不会触发子类的初始化) 访问类的静态方法 反射 Class.forName 初始化一个类的子类(会先初始化父类) 虚拟机启动时...; //如果包名是org.example.MathServiceImpl开头的,调用自定义类的findClass方法,否则调用父类的loadClass方法...; //利用反射实例化对象,和调用TwoNum类里面的twoNum方法 Object o = aClass.newInstance(); Method add
在虚拟机规范上,对这部分的规定并不具体,所以实现方式是很灵活的。...当需要调用一个类的方法的时候,只要知道这个方法在方法表中的偏移量就可以直接调用该方法了。 通过解析操作符号引用就可以直接转变为目标方法在类中方法表的位置,从而使得方法可以被调用。...所以,解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,也就是得到类或者字段、方法在内存中的指针或者偏移量。...即程序调用类的静态方法。 对类进行反射调用时,如果类没初始化,需要触发其初始化。 初始化一个类,如果其父类还未初始化,则先触发该父类的初始化。...需要注意的是,Java虚拟机对Class文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的Class文件加载到内存生成Class对象。
加载阶段完成后,虚拟机外部的二进制字节流就按照虚拟机所需的格式存储在方法区之中,而且在Java堆中也创建一个 java.lang.Class类的对象,这样便可以通过该对象访问方法区中的这些数据。...对于引用数据类型reference来说,如数组引用、对象引用等,如果没有对其进行显式地赋值而直接使用,系统都会为其赋予默认的零值,即null。...我们可以理解为static final常量在编译期就将其结果放入了调用它的类的常量池中 解析:把类中的符号引用转换为直接引用 解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,解析动作主要针对类或接口...、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。...并且只有调用了newInstance()方法采用调用构造函数,创建类的对象 。
TODO 在引用类型的值中还有一个特殊的值: null,当一个引用不指向任何对象的时候,它的值就用 null 来表示。Java 虚拟机规范并没有规定 null 在虚拟机实现中应当怎样编码表示。...特别地,当一个实例方法被调用的时候,第 0 个局部变量一定是用来存储被调用的实例方法所在的对象的引用(即 Java 语言中的“this”关键字)。...局部变量第一个局部变量,一定是当前对象的引用,即this关键字。...但类或接口的clinit方法只能由虚拟机自身隐式调用,没有任何虚拟机字节码指令可以调用这个方法。...虚拟机指令集大致可以分为下面几类: 加载和存储指令 运算指令 类型转换指令 对象创建于操作 操作数栈管理指令 控制转移指令 方法调用和返回指令 抛出异常 同步 因为虚拟机指令集很枯燥,就像linux命令一样
Java 虚拟机为 每个类 都准备了一张 方法表来存放类中所有的方法 。 当需要调用一个类的方法的时候,只要知道这个方法在 方法表中的偏移量 就可以直接调用该方法了。...通过 解析操作符号引用 就可以直接转变为 目标方法在类中方法表的位置 ,从而使得方法可以被调用。...所以,解析阶段是虚拟机将常量池内的 符号引用替换为直接引用的过程 ,也就是得到 类或者字段、方法在内存中的指针或者偏移量 。...即程序 **调用类的静态方法** 。对类进行 反射调用 时,如果类没初始化,需要触发其初始化。 初始化一个类,如果其 父类还未初始化 ,则先 触发该父类的初始化 。...需要注意的是,Java虚拟机对Class文件采用的是 按需加载 的方式,也就是说当需要使用该类时才会将它的Class文件加载到内存生成Class对象。
领取专属 10元无门槛券
手把手带您无忧上云