java 类加载机制有什么用
动态类加载主要是通过反射将类对象注入进去, 优点一大堆, 很多框架底层都有用到。
缺点:没有直接掉用直观方便。有些动态注入, 类型错误只有运行时才能发现。
在jdk1.2以后,类加载是通过委托来完成的,这意味着如果 ClassLoader 不能找到类,它会请求父代 ClassLoader 来执行此项任务,所有 ClassLoaders 的根是系统 ClassLoader,它会以缺省方式装入类 -- 即,从本地文件系统。详细见参考资料
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、子类引用父类的静态变量,不会导致子类初始化。
public class SupClass
{ public static int a = 123;
static
{
System.out.println("supclass init");
}
}public class SubClass extends SupClass
{ static
{
System.out.println("subclass init");
}
}public class Test
{ public static void main(String[] args)
{
System.out.println(SubClass.a);
}
}
执行结果:
supclass init123
2、通过数组定义引用类,不会触发此类的初始化
public class SupClass
{ public static int a = 123;
static
{
System.out.println("supclass init");
}
}public class Test
{ public static void main(String[] args)
{
SupClass[] spc = new SupClass[10];
}
}
执行结果:
3、引用常量时,不会触发该类的初始化
public class ConstClass
{ public static final String A= "MIGU";
static
{
System.out.println("ConstCLass init");
}
}public class TestMain
{ public static void main(String[] args)
{
System.out.println(ConstClass.A);
}
}
执行结果:
MIGU
用final修饰某个类变量时,它的值在编译时就已经确定好放入常量池了,所以在访问该类变量时,等于直接从常量池中获取,并没有初始化该类。
初始化的步骤
1、如果该类还没有加载和连接,则程序先加载该类并连接。
2、如果该类的直接父类没有加载,则先初始化其直接父类。
3、如果类中有初始化语句,则系统依次执行这些初始化语句。
在第二个步骤中,如果直接父类又有直接父类,则系统会再次重复这三个步骤来初始化这个父类,依次类推,JVM最先初始化的总是java.lang.Object类。当程序主动使用任何一个类时,系统会保证该类以及所有的父类都会被初始化。
动态类加载主要是通过反射将类对象注入进去, 优点一大堆, 很多框架底层都有用到。
缺点:没有直接掉用直观方便。有些动态注入, 类型错误只有运行时才能发现。
謇凤多维: 类的加载机制是先加载父类再加载子类,我感觉它的好处是可以让程序运行更快.
惠城区13012352666: Java程序类加载完全揭密内容是什么? ?
謇凤多维: 类加载是java语言提供的最强大的机制之一.尽管类加载并不是讨论的热点话题,但所有的编程人员都应该了解其工作机制,明白如何做才能让其满足我们的需要.这能有...
惠城区13012352666: 如何理解Java经典面试题中类的加载机制 - ?
謇凤多维: 两种方法都是线程安全的,第一种是在线程要使用getInstance的时候才去new,第二种在类加载的时候就new了 当instance占内存较大或者初始化时间长的时候,第二种会影响效率.
惠城区13012352666: java重新加载class文件 - ?
謇凤多维: Java类的加载是动态的,它并不会一次性将所有类全部加载后再运行,而是保证程序运行的基础类(像是基类)完全加载到jvm中,至于其他类,则在需要的时候才加载.这当然就是为了节省内存开销. Java的类加载器有三个,对应Java的三种...
惠城区13012352666: java动态类加载机制有什么缺点 - ?
謇凤多维: 动态类加载主要是通过反射将类对象注入进去, 优点一大堆, 很多框架底层都有用到.缺点:没有直接掉用直观方便.有些动态注入, 类型错误只有运行时才能发现.
惠城区13012352666: java的类不是运行时用到什么类才加载什么类吗,那么还有特别说反射机制干什么呢 - ?
謇凤多维: 总是有好处的. 举个例子.STRUTS框架来说.一个页面请求交给一个ACTION处理.偶们就可以用反射的方法.用这个请求的字符串反射到相应的类.那样就不用每个请求都要手动设定是交给哪个ACTION处理了.不是很方便么
惠城区13012352666: classloader的原理 有哪些类加载器 为什么要用自定义类加载器 - ?
謇凤多维: 原理之类的,你自己上网看资料吧,不是一两句话说得清的.至于为什么用自定义类加载器,个人总结了一下可能有下面几点吧,可能不全,也请大家补充:1. 加密:众所周知,java代码很容易被反编译,如果你需要把自己的代码进行加密,可以先将编译后的代码用某种加密算法加密,然后实现自己的类加载器,负责将这段加密后的代码还原.2. 从非标准的来源加载代码:例如你的部分字节码是放在数据库中甚至是网络上的,就可以自己写个类加载器,从指定的来源加载类.3. 动态创建:为了性能等等可能的理由,根据实际情况动态创建代码并执行.4. 其他(这个理由非常给力吧^_^)
惠城区13012352666: java中何时用到上下文加载器呢?在什么情况下用到.还有何时用到类加载器?小弟不懂,求高手解答. - ?
謇凤多维: 这个问题经常出现在编写框架代码 , 需要动态加载很多类和资源的时候 . 通常当你需要动态加载资源的时候 , 你至少有三个 ClassLoader 可以选择 :系统类加载器或叫作应用类加载器 (system classloader or application classloader) 当前类...
惠城区13012352666: Java - java的类加载机制是怎样的 - ?
謇凤多维: 在jdk1.2以后,类加载是通过委托来完成的,这意味着如果 ClassLoader 不能找到类,它会请求父代 ClassLoader 来执行此项任务,所有 ClassLoaders 的根是系统 ClassLoader,它会以缺省方式装入类 -- 即,从本地文件系统.详细见参考资料
惠城区13012352666: java热部署需要哪些知识 - ?
謇凤多维: 1. 所谓热部署,就是在应用正在运行的时候升级软件,却不需要重新启动应用.1.1对于Java应用程序来说,热部署就是在运行时更新Java类文件.1.2在基于Java的应用服务器实现热部署的过程中,类装入器扮演着重要的角色.1.3大多数基于...