java类加载
A. java中关于类加载。
首先要有该类的class文件所在的文件夹
然后,用classLoader载入这个文件夹中的所有以class结尾的文件,然后调用这个class对象的isAnnotationPresent({注解}.class).判断是不是有加注解
class类也可以通过反射查找到这个类或者这个方法上有没有加这个注解。但这是通过类找到注解
主要是想通过注解找到加了这个注解的所有类,
B. java的类加载后什么时候会被释放
java的类加载后且当使用阶段完成之后,java类就进入了卸载阶段,也就是所谓的释放。
使用阶段包括主动引用和被动引用,主动饮用会引起类的初始化,而被动引用不会引起类的初始化。
一个java类的完整的生命周期会经历加载、连接、初始化、使用、和卸载五个阶段,当然也有在加载或者连接之后没有被初始化就直接被使用的情况,如图所示:
PS:关于类的卸载,在类使用完之后,如果满足下面的情况,类就会被卸载:
该类所有的实例都已经被回收,也就是java堆中不存在该类的任何实例。
加载该类的ClassLoader已经被回收。
该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法。
如果以上三个条件全部满足,jvm就会在方法区垃圾回收的时候对类进行卸载,类的卸载过程其实就是在方法区中清空类信息,java类的整个生命周期就结束了。
C. java程序什么是类加载
你可以了解一下 深入理解java虚拟机,
java类加载 是因为在运行时当它需要引用某个类的时候,会先去加载这个类,就是去读这个class文件到内存里面来,现在还没有创建这个类的实例,
你可以理解为 你写的java代码在编译成class文件后,并没有去执行,或者去引用他,只有程序运行时它将要使用这个类的时候才会去读取这个class文件,这时候叫做类加载,当缓存了这个类文件之后,后面的创建类的时候都会去引用它,因为类加载是运行是加载,所以java代码在运行时是有办法修改的,同样java类加载也允许加载一个远程的class文件,也代表它是支持程序不停止时更新程序代码的。
D. java如何加载一个外部的类或class文件
首先import 类,之后object来装Class.forName()。inner.现在这object有了import类的所有方法
这forName里的路径该写你的类的名字,如果在包里要加包名
E. java类加载顺序
记住 3 条原则:
1、父类优先于子类
2、属性优先于代码块优先于构造方法
3、静态优先于非静态
因此,类加载顺序为:
父类静态变量->父类静态语句块->子类静态变量->子类静态语句块->父类普通成员变量->父类动态语句块->父类构造器->子类普通成员变量->子类动态语句块->子类构造器
F. java 类加载机制有什么用
AVA类加载机制详解
“代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,却是变成语言发展的一大步”,这句话出自《深入理解JAVA虚拟机》一书,后面关于jvm的系列文章主要都是参考这本书。
JAVA源码编译由三个过程组成:
1、源码编译机制。
2、类加载机制
3、类执行机制
我们这里主要介绍编译和类加载这两种机制。
一、源码编译
代码编译由JAVA源码编译器来完成。主要是将源码编译成字节码文件(class文件)。字节码文件格式主要分为两部分:常量池和方法字节码。
二、类加载
类的生命周期是从被加载到虚拟机内存中开始,到卸载出内存结束。过程共有七个阶段,其中到初始化之前的都是属于类加载的部分
加载----验证----准备----解析-----初始化----使用-----卸载
系统可能在第一次使用某个类时加载该类,也可能采用预加载机制来加载某个类,当运行某个java程序时,会启动一个java虚拟机进程,两次运行的java程序处于两个不同的JVM进程中,两个jvm之间并不会共享数据。
1、加载阶段
这个流程中的加载是类加载机制中的一个阶段,这两个概念不要混淆,这个阶段需要完成的事情有:
1)通过一个类的全限定名来获取定义此类的二进制字节流。
2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3)在java堆中生成一个代表这个类的Class对象,作为访问方法区中这些数据的入口。
由于第一点没有指明从哪里获取以及怎样获取类的二进制字节流,所以这一块区域留给我开发者很大的发挥空间。这个我在后面的类加载器中在进行介绍。
2、准备阶段
这个阶段正式为类变量(被static修饰的变量)分配内存并设置类变量初始值,这个内存分配是发生在方法区中。
1、注意这里并没有对实例变量进行内存分配,实例变量将会在对象实例化时随着对象一起分配在JAVA堆中。
2、这里设置的初始值,通常是指数据类型的零值。
private static int a = 3;
这个类变量a在准备阶段后的值是0,将3赋值给变量a是发生在初始化阶段。
3、初始化阶段
初始化是类加载机制的最后一步,这个时候才正真开始执行类中定义的JAVA程序代码。在前面准备阶段,类变量已经赋过一次系统要求的初始值,在初始化阶段最重要的事情就是对类变量进行初始化,关注的重点是父子类之间各类资源初始化的顺序。
java类中对类变量指定初始值有两种方式:1、声明类变量时指定初始值;2、使用静态初始化块为类变量指定初始值。
初始化的时机
1)创建类实例的时候,分别有:1、使用new关键字创建实例;2、通过反射创建实例;3、通过反序列化方式创建实例。
new Test();
Class.forName(“com.mengdd.Test”);
2)调用某个类的类方法(静态方法)
Test.doSomething();
3)访问某个类或接口的类变量,或为该类变量赋值。
int b=Test.a;
Test.a=b;
4)初始化某个类的子类。当初始化子类的时候,该子类的所有父类都会被初始化。
5)直接使用java.exe命令来运行某个主类。
除了上面几种方式会自动初始化一个类,其他访问类的方式都称不会触发类的初始化,称为被动引用。
1、子类引用父类的静态变量,不会导致子类初始化。
执行结果:
MIGU
用final修饰某个类变量时,它的值在编译时就已经确定好放入常量池了,所以在访问该类变量时,等于直接从常量池中获取,并没有初始化该类。
初始化的步骤
1、如果该类还没有加载和连接,则程序先加载该类并连接。
2、如果该类的直接父类没有加载,则先初始化其直接父类。
3、如果类中有初始化语句,则系统依次执行这些初始化语句。
在第二个步骤中,如果直接父类又有直接父类,则系统会再次重复这三个步骤来初始化这个父类,依次类推,JVM最先初始化的总是java.lang.Object类。当程序主动使用任何一个类时,系统会保证该类以及所有的父类都会被初始化。
G. java中类加载的两种方法是什么
java类有两种方法一种是类方法就是用static修饰的,一种是实例方法,就是没有static修饰的方法
H. java 类加载先后顺序
父类态代码块
父类静态属性
//以上根据代码顺序
子类静态属性
子类静态代码块
//以上根据代码顺序
父类属性
父类代码块
//以上根据代码顺序
父类构造器
子类属性
子类代码块
//以上根据代码顺序
子类构造方法
子类方法
父类方法
父类静态方法
子类静态方法
package com.zz;
/**
* Created by @摩西摩西 2020/3/21 22:29
**/
public class Father {
public String name=Son.getmetod("父类属性");
public Father(){
System.out.println("父类构造器");
}
{
System.out.println("父类代码块");
}
public void fatherMethod(){
System.out.println("父类方法");
}
static {
System.out.println("父类态代码块");
}
static String name1=Son.getmetod("父类静态属性");
public static void fatherStaticMethod(){
System.out.println("父类静态方法");
}
}
package com.zz;
/**
* Created by @摩西摩西 2020/3/21 22:32
**/
public class Son extends Father {
public String name = getmetod("子类属性");
public Son() {
System.out.println("子类构造方法");
}
{
System.out.println("子类代码块");
}
public void sonMethod(){
System.out.println("子类方法");
}
public static String name1 = getmetod("子类静态属性");
static {
System.out.println("子类静态代码块");
}
public static void sonStaticMethod() {
System.out.println("子类静态方法");
}
public static String getmetod(String s) {
System.out.println(s);
return s;
}
public static void main(String[] args) {
Son son= new Son();
son.sonMethod();
son.fatherMethod();
fatherStaticMethod();
sonStaticMethod();
}
}
I. java类加载器有几种
Java中加载器的种类大致可以分为四种:Bootstrap ClassLoader(由C++语言写成),系统加载器(也就是内部类AppClassLoader),ExtClassLoader,以及java.net.UrlClassLoader.
当我们运行一个程序时,首先是找到JDK安装目下的jvm.dll来启动JAVA虚拟机,而后Bootstrap ClassLoader产生,接下来就是Bootstrap ClassLoader来加载ExtClassLoader,并且指定ExtClassLoader的父加载器为Bootstrap ClassLoader,但是因为Bootstrap ClassLoader用C++语言写的,所以用JAVA的观点来看,这个加载器的实例是不存在的,所以ExtClassLoader的父加载器被设置为了null,然后就是Bootstrap ClassLoader将AppClassLoader装载,并指定其父加载器为ExtClassLoader。
JAVA是按照加载器的委派模型来实现的。这种模型是JAVA安全性机制的保证。并且值得我们注意的就是这几个加载器的默认加载类的路径。对于AppCLassLoder来说,它的路径也就是我们的classpath里面的路径。而对于ExtClassLoader来说,它的路径是jre\lib\ext\classes.对于URLClassLoader来说,它的加载路径是我们指定的url。