精华内容
下载资源
问答
  • 最近在测试项目代码中遇到同一个类不同classloader加载后出现的问题: 类A中有一个字段a,它的类型为X 类B中有一个字段b,它的类型也为X 类A由classLoaderA所加载,类B由classLoaderB所加载 执行赋值语句A...

    最近在测试项目代码中遇到同一个类由不同的classloader加载后出现的问题:

    1. 类A中有一个字段a,它的类型为X
    2. 类B中有一个字段b,它的类型也为X
    3. 类A由classLoaderA所加载,类B由classLoaderB所加载
    4. 执行赋值语句A.a = B.b,由于这两个类型均为X,可以执行,但是有一个要求,这个要求就是在A中所装载类X的装载器必须和在B中装载类X的装载器相同,否则赋值语句失败

        为什么会产生上面的输出,我们可以来看一个以下的代码

     首先是一个简单的类调用:

    类Foo3

    1 public class Foo3 implements IFoo{
    2     public void hello() throws Exception{
    3         Class<?> clazz = Foo.class;
    4         Foo foo2 = Foo4.foo;
    5     }
    6 }

    在上面的代码中,变量foo2引用了类Foo4的一个静态引用:

    1 public class Foo4 {
    2     public static Foo foo = new Foo();
    3 }

    类Foo是一个非常简单的java类,即普通的java类:

    1 public class Foo implements IFoo{}

      重点在于如何运行这段代码,我们运行一段代码,分别使用两个类加载器来加载同一个类类Foo,运行代码如下

    1 MyClassLoader3 myClassLoader3 = new MyClassLoader3(T.class.getClassLoader());
    2 IFoo foo3 = (IFoo) (myClassLoader3.loadClass("com.m_ylf.study.java.classLoad.Foo3").newInstance());
    3 foo3.hello();

    在上面的代码中,采用自定义的classLoader来定义类Foo3,我们来看具体的定义:

    1 public Class<?> loadClass(String name) throws ClassNotFoundException {
    2     if("Foo".equals(name) ) {
    3         //自定义
    4     }
    5     if("Foo3".equals(name) ) {
    6         //自定义
    7     }
    8     return super.loadClass(name);
    9 }

     其实就是将类类Foo和类Foo3交由classLoader3即我们自定义加载器来加载,其它的类仍交由super即appClassLoader来加载。现在运行这段代码,即会有一个出错信息,出错信息如下:

    Exception in thread "main" java.lang.LinkageError: loader constraint violation: when resolving field "foo" the class
    loader (instance of MyClassLoader3) of the referring class, Foo4, and the class loader (instance of sun/misc
    /Launcher$AppClassLoader) for the field's resolved type, /Foo, have different Class objects for that type
        at Foo3.hello(Foo3.java:7)

      错误在第7行,即Foo foo2 = Foo4.foo;这一行出错了。

        为什么会出错,我来看来第一行代码:Class<?> clazz = Foo.class;这段代码,会对Foo类进行加载,采用的加载器为myClassLoader3,即加载Foo3类时所使用的加载器。这句话运行之后,即表示类Foo已经被加载了,且加载器为myClassLoader3。
        第二行代码:Foo foo2 = Foo4.foo。这段代码会初始化Foo4,由于myClassLoader3并没有特殊处理Foo4,所以将由父类加载器,即AppClassLoader来加载,在加载过程中,因为调用到了Foo4.foo,所以会加载Foo类。这个加载是在Foo4类初始化时进行加载的。因为在碰到类Foo时,appClassLoader显示其从未加载过foo(先前的foo是由myClassLoader加载的,而不是由appClassLoader加载的),所以又会加载Foo。
        这时候,类Foo就会有两个类加载器,一个是由myClassLoader3加载的,另一个是由appClassLoader加载的。如果两个类分开运行,代码是没有问题的。
        问题就出在这个赋值语句,或者说是对象引用上。在Foo3内部使用Foo4.foo时,JVM会记录Foo4.foo在foo3内部的类引用和加载器,在这个运行代码中,此加载器为myClassLoader,因为在调用Foo4.foo之前已经加载了Foo。然而,在引用时,它将得到声明Foo4.foo时的Foo类型的加载器,在Foo4.foo中, Foo类型的加载器为appClassLoader。JVM在运行时会对这两个加载器进行验证,JVM规范中要求这两个加载器必须要一致,否则将报类验证错误,即VerifyError的错误,这是为了防止不正常的类冒充正确的类进行类型欺骗。如在类Foo3中的Foo是来自于黑客故意构建的一个类时。

        我们再来看关于jbmp的问题,这是由于引用juel.jar时,里面有一个类如ExpressionFactory类,此类在类JspApplicationContext中被声明。在juel.jar中,类ExpressionFactory已经被jspClassLoader加载了,现在要进行赋值语句,即=由jspContext中取得的expressionFactory对象。而JspApplicationContext是由Tomcat的StandardClassLoader类加载的,在类JspApplicationContext中声明的expressionFactory字段自然也是由StandardClassLoader类加载的。现在两个由不同类加载器加载的同一个对象要进行引用操作,自然不能通过JVM的验证了。
        总而言之,就是说JVM在引用其它类的字段,或者调用其它类的方法时,将进行类型验证。验证包括,字段的类型验证,方法的返回类型验证,方法参数类型验证等。验证的内容就验证在调用方和被调用方时,同一个类的加载器是否一致。即在调用方时,记录的字段(参数)类型的加载器与被调用方法记录的字段(参数)类型的加载器是否一致。如果不一致,自然就不会被JVM验证通过。

    ref:http://www.iflym.com/index.php/code/understand-jvm-load-constraint.html

     

    上面这篇blog和我在项目中遇到的问题是一致的,我们在项目中需要对旧版本的Class对象就行替换,之前的做法仅仅是把Impl中值给替换了,之后在debug过程中发现这样是不够的,因为在tuscany的加载过程中它会对具体的implementation实现进行Introspection来检查这个实现中有哪些Reference、Service等等,它会将Reference的字段保存下来,然后在运行过程中通过相应的Injector来进行注入,一开始的做法,我们是将Injector里面保存的method和field用新版本的给替换(因为我们发现tuscany里面的注入的具体实现是通过反射来实现的),这样改完之后运行时就出现了上面blog中出现的问题。

    仔细分析了下错误原因,我们发现tuscany通过反射注入的值是旧版本的,而我们的method、field对象都是新版本的,这样就会出现IllegalArgumenException错误,分析之后得出结论:tuscany用来生成注入值所使用的字段接口仍然是旧版本的,也就是说我们的替换不完全,通过对WireObjectFactory中保存的interfaze的替换,将旧版本从中移除,这样反射时就不会出错了

     

    在调试过程中还遇到另外一个问题,由于field是private类型的,当我们需要对它进行注入时取消java语言访问控制检查

    1 newField.setAccessible(true);

     

     

    转载于:https://www.cnblogs.com/feiling/archive/2013/01/12/2857682.html

    展开全文
  • 不同ClassLoader加载的同名类属于不同的类型,不能相互转化和兼容。...运行如下代码,使用不同的类加载器加载同一个类(源代码都一样,不过一个来自bin目下的.class,一个来自D:\temp下的.class)  Java Code

     

    由不同ClassLoader对象加载的同名类属于不同的类型,不能相互转化和兼容。

    新建一个工程NotSameClass。将如下代码,一份放入NoSameClass工程源代码目录下,一份编译成.class放入D:\temp目录下


    运行如下代码,使用不同的类加载器加载同一个类(源代码都一样,不过一个来自bin目下的.class,一个来自D:\temp下的.class

     Java Code 

     

    package com.bjsxt.test;
    import java.io.ByteArrayOutputStream;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;

    public class Test {

        
    public static void main(String[] args) {
            
            
    //先用应用类加载器加载HelloLoader
            HelloLoader object1=new HelloLoader();
            System.out.println(object1.getClass().getClassLoader());
            
            
    //再用扩展类加载器加载HelloLoader
            ClassLoader cl = ClassLoader.getSystemClassLoader();
            
    try {
                
    byte[] classBytes = loadClassBytes("com.bjsxt.test.HelloLoader");
                
                Method defineClassMethod = ClassLoader.
    class.getDeclaredMethod("defineClass"byte[].classint.classint.class);
                defineClassMethod.setAccessible(true);
                defineClassMethod.invoke(cl.getParent(), classBytes, 
    0, classBytes.length);
                
                Class<?> clazz = cl.getParent().loadClass(
    "com.bjsxt.test.HelloLoader");
                System.out.println(clazz.getClassLoader());
                
                
    //两个不同类的对象强制类型转换
                object1=(HelloLoader)clazz.newInstance();
                
            } 
    catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
    catch (SecurityException e) {
                e.printStackTrace();
            } 
    catch (IllegalAccessException e) {
                e.printStackTrace();
            } 
    catch (IllegalArgumentException e) {
                e.printStackTrace();
            } 
    catch (InstantiationException e) {
                e.printStackTrace();
            } 
    catch (NoSuchMethodException e) {
                e.printStackTrace();
            } 
    catch (InvocationTargetException e) {
                e.printStackTrace();
            }
            
        }
        
        
    /**
         * 
    将包名中的.替换成路径分隔符,从D:/temp/目录下查找这个文件,如果存在的话,将其读取到字节数组
         * @param name
         * @return
         */

        
    public static byte[] loadClassBytes(java.lang.String name) {
            
            
    String path="D:/temp/"+name.replace(".""/")+".class";
            
            InputStream is=null;
            ByteArrayOutputStream baos=null;
            
            
    try {
                is=
    new FileInputStream(path);
                
                baos=
    new ByteArrayOutputStream();
                
                
    byte[] buffer=new byte[1024];
                
                
    int ret=0;
                
    while((ret=is.read(buffer))!=-1){
                    baos.write(buffer, 
    0, ret);
                }
                
                
    return baos.toByteArray();
                
            } 
    catch (FileNotFoundException e) {
                e.printStackTrace();
            } 
    catch (IOException e) {
                e.printStackTrace();
            }
    finally{
                
    try {
                    
    if(is!=null)
                        is.close();
                    
                    
    if(baos!=null)
                        baos.close();
                } 
    catch (IOException e) {
                    e.printStackTrace();
                }
            }
            
            
    return null;
        }
    }

     


     

    并且,即便是同一类 类加载器,不同的对象加载出来的类也不是同一个类。


     

     

    展开全文
  • 一般同一个ClassLoader只能加载一个同名的,但是老大想我做一个向下兼容检测的程序. 遇到一个问题,无法加载两个同名的ClassLoader. 请问下如何创建两个不同ClassLoader
  • 近期研究classloader,有个疑问:有人说:每个ClassLoader都维护了一份自己的名称空间, 同一个名称空间里不能 出现两个同名的。有些疑问,同名是指的类名相同,如果包路径不同的话算不算同名,这种类加载时会...

    近期研究classloader,

    有个疑问:

    有人说:每个ClassLoader都维护了一份自己的名称空间, 同一个名称空间里不能 出现两个同名的类。 有些疑问,同名类是指的类名相同,如果包路径不同的话算不算同名类,这种类加载时会不会出现问题。

    自己在自己的系统中写了一套测试内容,使用main方法执行自定义classloader加载系统所有的类,遇到2个类名相同,但是包路径不同,加载出现java.lang.LinkageError: duplicate class definition异常。

    但是如果使用tomcat启动的时候这两个类却可以顺利通过加载,看了下tomcat启动的时候加载类使用的是WebappClassloader。

    为什么? 大家说说呗。

    问题补充:自定义的loader代码:

    package cn.sforce.test.startup.classloader;

    import java.io.ByteArrayInputStream;

    import java.io.File;

    import java.io.FileInputStream;

    import java.io.InputStream;

    import java.net.URL;

    import java.util.ArrayList;

    import java.util.HashMap;

    import cn.sforce.test.startup.TestOut;

    import cn.sforce.test.startup.TestURLStreamHandler;

    import cn.sforce.test.startup.Util;

    public class UnitClassLoader extends ClassLoader

    {

    protected static TestOut log = TestOut.getLogger( UnitClassLoader.class.getName() );

    /**

    * 驱动程序列表

    */

    private static String driverLibList[] = null;

    /**

    * WEB公共库

    */

    private static String freezeLibList[] = null;

    /**

    * 应用的类路径

    */

    protected String webPath = null;

    protected String webClazzPath = null;

    /**

    * 父装载器

    */

    private ClassLoader parent = null;

    // 从库中加载的类

    private HashMap clazzList = new HashMap();

    private HashMap fileList = new HashMap();

    // 工程类装载器

    private ArrayList jarLoaderList = new ArrayList();

    public UnitClassLoader( ClassLoader parent, String webPath, String... projPath ) throws Exception

    {

    super( parent );

    this.parent = parent;

    this.webPath = webPath;

    this.webClazzPath = webPath + "/WEB-INF/classes/";

    // 加载系统JAR文件

    loadAllJar();

    // 初始化类装载器

    URL root = System.class.getResource( "/" );

    String classPath = root.getPath().replace( '\\', '/' );

    if( classPath != null ){

    //linkProjSource( classPath );

    }

    // 关联类的装载器

    if( projPath != null ){

    for( String path : projPath ){

    //linkProjSource( path );

    }

    }

    }

    /**

    * 加载系统JAR文件

    * @throws Exception

    */

    private void loadAllJar() throws Exception

    {

    String driverPath = this.getClass().getResource("/").getFile();

    if( driverPath.endsWith("/bin/") ){

    driverPath = driverPath.substring( 0, driverPath.length()-4 );

    }

    else if( driverPath.endsWith("/classes/") ){

    driverPath = driverPath.substring( 0, driverPath.length()-8 );

    }

    driverPath += "lib/";

    log.info( "驱动程序库文件的目录 = " + driverPath );

    driverLibList = Util.getFileList( driverPath, "jar" );

    for( int ii=0; ii

    String fileName = driverPath + driverLibList[ii];

    JarLoader.loadAllFile( clazzList, fileList, fileName );

    }

    // 不加载的库

    String ex[] = {

    "axiom-api-1.2.5.jar",

    "axiom-dom-1.2.5.jar",

    "axiom-impl-1.2.5.jar",

    "axis2-adb-1.3.jar",

    "axis2-kernel-1.3.jar",

    "axis2-metadata-1.3.jar",

    "axis2-xmlbeans-1.3.jar",

    "neethi-2.0.2.jar",

    "wsdl4j-1.6.2.jar",

    "ws-policy-SNAPSHOT.jar",

    "je-3.1.0.jar",

    "jfreechart-1.0.12.jar",

    "jcommon-1.0.10.jar",

    "itext-2.1.7.jar",

    "itext-rtf-2.1.7.jar",

    "iTextAsian.jar",

    "XmlSchema-1.4.2.jar",

    "poi-3.6-20091214.jar",

    "poi-contrib-3.6-20091214.jar",

    "poi-scratchpad-3.6-20091214.jar",

    "mail.jar",

    "lucene-core-2.0.0.jar",

    "ant.jar",

    "antlr-2.7.5.jar",

    "jasperreports-4.0.2.jar",

    "annogen-0.1.0.jar",

    "commons-digester-1.7.jar",

    "commons-fileupload-1.2.1.jar",

    "commons-httpclient-3.0.1.jar",

    "sforce-commons-el-1.0.jar",

    "org-netbeans-lib-cvsclient.jar",

    "servlet-api.jar",

    "velocity-1.5.jar",

    "wstx-asl-3.2.5.jar",

    "xalan-2.7.0.jar"

    };

    int x = 0;

    String libPath = webPath + "/WEB-INF/lib/";

    freezeLibList = Util.getFileList( libPath, "jar" );

    for( int ii=0; ii

    String fileName = freezeLibList[ii];

    for( x=ex.length-1; x>=0; x-- ){

    if( ex[x].compareTo(fileName) == 0 ){

    break;

    }

    }

    if( x < 0 ){

    JarLoader.loadAllFile( clazzList, fileList, libPath + fileName );

    }

    }

    }

    /**

    * @param clazzName

    * @param resolve

    * @return java.lang.Class

    * @throws java.lang.ClassNotFoundException

    */

    public Class> loadClass(String clazzName, boolean resolve)

    throws LinkageError, ClassNotFoundException

    {

    Class> clazz = null;

    // 加载关联项目的类

    for( ProjLoaderInfo l : jarLoaderList ){

    clazz = l.loadClass( clazzName, resolve );

    if( clazz != null ){

    return clazz;

    }

    }

    // 如果不需要刷新,从缓存中装入

    clazz = findLoadedClass(clazzName);

    if( clazz != null ){

    return clazz;

    }

    // 读类文件并装入

    FreezeResource c = clazzList.get( clazzName );

    if( c != null ){

    byte data[] = c.getClazzData();

    clazz = loadClass( clazzName, data );

    if( clazz != null ){

    if( resolve ){

    System.out.println("unit加载类---------->"+clazz.getName());

    resolveClass(clazz);

    }

    return clazz;

    }

    }

    try{

    byte[] data = loadClazzData( clazzName );

    if( data != null ){

    clazz = loadClass( clazzName, data );

    }

    }

    catch( LinkageError e ){

    throw e;

    }

    catch( Throwable ex ){

    }

    // 如果上面没有成功,尝试用默认的ClassLoader装入它

    if (clazz == null){

    try{

    //clazz = findSystemClass(name);

    clazz = this.getParent().loadClass(clazzName);

    }

    catch( ClassNotFoundException e ){

    throw new ClassNotFoundException( "加载类[" + clazzName + "]时错误", e );

    }

    }

    if( clazz == null ){

    throw new ClassNotFoundException( "加载类[" + clazzName + "]时错误" );

    }

    else if( resolve ){

    resolveClass(clazz);

    }

    return clazz;

    }

    /**

    * @param className

    * @return java.lang.Class

    * @throws java.lang.ClassNotFoundException

    */

    public Class> loadClass(String className) throws ClassNotFoundException

    {

    return loadClass( className, false );

    }

    /**

    * @param className

    * @return java.lang.Class

    * @throws java.lang.ClassNotFoundException

    */

    public Class> findClass(String className) throws ClassNotFoundException

    {

    // 先查找缓冲区

    Class> clazz = findLoadedClass( className );

    if( clazz == null ){

    byte[] data = loadClazzData( className );

    if( data != null ){

    clazz = loadClass( className, data );

    }

    }

    if( clazz == null ){

    throw new ClassNotFoundException( "加载类[" + className + "]时错误" );

    }

    return clazz;

    }

    /**

    * @param className

    * @return java.lang.Class

    * @throws java.lang.ClassNotFoundException

    */

    protected Class> loadClass(String className, byte[] data) throws ClassNotFoundException

    {

    Class> clazz;

    try{

    clazz = defineClass(className, data, 0, data.length);

    }

    catch( ClassFormatError e ){

    log.error( "类文件[" + className + "]格式错误" );

    throw new ClassNotFoundException( "类文件[" + className + "]格式错误", e );

    }

    return clazz;

    }

    /**

    * @param clazzName

    * @return byte[]

    * @throws java.lang.ClassNotFoundException

    */

    protected byte[] loadClazzData( String clazzName )

    {

    InputStream is = null;

    try {

    // 从当前工程加载类

    String fileName = webClazzPath + clazzName.replace('.', '/') + ".class";

    File fp = new File( fileName );

    if( !fp.exists() ){

    throw new ClassNotFoundException( "类文件[" + clazzName + "]不存在" );

    }

    try {

    is = new FileInputStream( fp );

    }

    catch( Throwable e ){

    throw new ClassNotFoundException( "加载类[" + clazzName + "]时错误", e );

    }

    return Util.readFile( is );

    }

    catch( Throwable e ){

    return null;

    }

    finally{

    Util.closeInputStream( is );

    }

    }

    /**

    * 是否有效的类

    * @param clazz

    * @return

    */

    protected boolean isLoadedClass( Class> clazz )

    {

    ClassLoader loader = clazz.getClassLoader();

    if( loader == this ){

    return true;

    }

    for( ProjLoaderInfo l : jarLoaderList ){

    if( l.getLoader() == loader ){

    return true;

    }

    }

    return false;

    }

    /**

    * 检查类是否已经更新

    * @return

    */

    public void chechClazzModify()

    {

    boolean flag = false;

    for( ProjLoaderInfo l : jarLoaderList ){

    // 不要检查junit的类

    String path = l.getClassPath();

    if( path.indexOf("junit-") < 0 && path.indexOf("freeze") < 0 ){

    if( l.chechClazzModify() ){

    flag = true;

    break;

    }

    }

    }

    // 清空所有类装载器

    if( flag ){

    System.out.println( "清空所有已经装载的类" );

    for( ProjLoaderInfo l : jarLoaderList ){

    // 不要清空junit的类

    String path = l.getClassPath();

    if( path.indexOf("junit-") < 0 && path.indexOf("freeze") < 0 ){

    l.clear();

    }

    }

    }

    }

    public InputStream getResourceAsStream( String fileName )

    {

    int ptr = fileName.indexOf( ':' );

    if( ptr > 0 ){

    String f1 = fileName.substring( 0, ptr );

    String f2 = fileName.substring( ptr+1 );

    if( f1.endsWith("/test-unit") ){

    FreezeResource t = fileList.get( f2 );

    if( t != null ){

    byte data[] = t.getClazzData();

    return new ByteArrayInputStream( data );

    }

    }

    }

    InputStream is = this.getClass().getResourceAsStream( fileName );

    if( is != null ){

    return is;

    }

    FreezeResource t = fileList.get( fileName );

    if( t != null ){

    byte data[] = t.getClazzData();

    return new ByteArrayInputStream( data );

    }

    is = super.getResourceAsStream( fileName );

    if( is != null ){

    return is;

    }

    return null;

    }

    public URL getResource( String path )

    {

    if( path == null ){

    return null;

    }

    path = normalize(path);

    if (path == null){

    return null;

    }

    FreezeResource t = fileList.get( path );

    if( t != null ){

    try{

    TestURLStreamHandler u = new TestURLStreamHandler();

    u.setData( t.getClazzData() );

    return new URL( null, null, -1, path, u );

    }

    catch( Throwable e ){

    }

    }

    URL url = super.getResource( path );

    if( url != null ){

    return url;

    }

    if( path.charAt(0) != '/' ){

    path = "/WEB-INF/classes/" + path;

    }

    File file = new File( webPath + path );

    if(file.exists() == false){

    return null;

    }

    try{

    // log.info( path + " ==> " + file.toURL() );

    return file.toURL();

    }

    catch( Exception e ){

    return null;

    }

    }

    private String normalize(String path) {

    String normalized = path;

    if (normalized.indexOf('\\') >= 0){

    normalized = normalized.replace('\\', '/');

    }

    // Resolve occurrences of "/../" in the normalized path

    while (true) {

    int index = normalized.indexOf("/../");

    if (index < 0)

    break;

    if (index == 0)

    return (null);  // Trying to go outside our context

    int index2 = normalized.lastIndexOf('/', index - 1);

    normalized = normalized.substring(0, index2) +

    normalized.substring(index + 3);

    }

    // Return the normalized path that we have completed

    return (normalized);

    }

    /**

    * 初始化关联的Project

    */

    public void linkProjSource( String output )

    {

    if( output.indexOf("freeze-unit") >= 0 ){

    return;

    }

    if( output.endsWith("/") == false ){

    output = output + "/";

    }

    // 检查是否已经存在

    for( ProjLoaderInfo j : jarLoaderList ){

    String path = j.getClassPath();

    if( path.compareTo(output) == 0 ){

    return;

    }

    }

    try{

    ProjLoaderInfo l = new ProjLoaderInfo( parent, this, webPath, output );

    jarLoaderList.add( l );

    }

    catch( Throwable e ){

    }

    }

    public String getWebPath()

    {

    return webPath;

    }

    public String getWebClazzPath()

    {

    return webClazzPath;

    }

    }

    展开全文
  • 同一个ClassLoader能够重复加载同一个类?同一个ClassLoader不允许多次加载一个类的,否则会报java.lang.LinkageError; JVM只提供了加载类的方法,但并没有提供卸载的方法(主动回收,可预期),当发生FGC时才被...

    基础知识

    1. JVM如何区分不同类型? JVM通过类全名+加载该类的ClassLoader区分的;
    2. 同一个ClassLoader能够重复加载同一个类?同一个ClassLoader不允许多次加载一个类的,否则会报java.lang.LinkageError;
    3. JVM只提供了加载类的方法,但并没有提供卸载的方法(主动回收,可预期),当发生FGC时才被回收(被动回收,不可预期)

    ClassLoader类继承关系

      注意区别“ClassLoader类继承关系”与“类加载器组织关系”,下图是从Java语法角度说明的ClassLoader相关类之间的继承关系:
    ClassLoader类继承关系

    ClassLoader重要方法

    loadClass(重要):双亲委托机制的体现,先委托父类加载器加载,加载不到再自己加载,如果想自定义类加载机制需要继承ClassLoader,覆盖loadClass方法实现
    loadclass
    findClass:当前类加载器查找类的逻辑,当父类加载器没有加载到指定类时被调用。

    ClassLoader.loadClass()过程

    1. 查看当前ClassLoader是否已加载该类:以ClassLoader和类全名为key到SystemDictionary 查询;
    2. 若查询不到则委托父类加载器加载;
    3. 若仍加载不到,则调用findClass();
    展开全文
  • 一.看前须知  1.jvm会校验class文件的完整性和准确性,然后加载...同一个包类名且同一个类加载器加载的,是同一个类.(这意味着使用不同的加载器来加载同一个class文件,那就不是同一个类,我们会在后面去验证这个道理....
  • 同一个Class,如果是由不同类加载器实例加载的,那么它们的类型是不相同的
  • 不同分支加载同一个class文件会被认为是不同的class,不可直接互相访问 比方说class A 分别被两个分支上的classLoader 加载,分别生成a1,a2两个实例, 如果两个实例都持有对方的引用, 在a1 中调 a2.f();或在a2...
  • 在JVM中表示两个class对象是否为同一个类存在两个必要条件: 类的完整类名必须一致, 包括包名。 加载这个类的ClassLoader (指ClassLoader实例对象)必须相同。 换句话说,在JVM中,即使这两个类对象(class对象)来源...
  • 目录判断是否是同一个类的标准 判断是否是同一个类的标准 在JVM中表示两个class对象是否为同一个类的两个必要条件: 类的完整类名必须一致,包括包名。 加载这个类的ClassLoader(指ClassLoader实例对象)必须相同...
  • java之classloader

    2012-07-22 18:02:00
    1.两个不同classloader加载同一个类: 2.使用自定义的classloader加载自定义的java.lang.Object:抛出SecurityException:禁止包名:java.lang。要加载一个类最后都必须调用classloader的defineClass(...)方法,...
  • 分析ClassLoader

    2016-09-30 10:11:12
    不同类加载器加载一个类,类初始化块会被执行几次,不同ClassLoader加载的类存放在哪里,是否指向同一个Class实例 类A触发了类B的加载,那么类B的加载器是什么 如何实现热部署,即在运行时改变类的行为,或类替换 ...
  • 即使两个类来源于同一个Class文件,只要加载它们的类加载不同,这两个类就不相等。 类加载器有哪些? 启动类加载器(Bootstrap ClassLoader):使用C++实现(仅限于HotSpot),是虚拟机自身的一部分。负责将存放...
  • Java-ClassLoader 知识

    2019-03-06 15:30:01
    下面给出的Java中ClassLoader中的描述,哪些描述是正确的?( ) A.ClassLoader没有层次关系 B.... C....不同ClassLoader加载同一个Class文件,所得的是相同的 解析:A选项错误,ClassLoad...
  • ClassLoader笔记

    2016-03-16 20:49:48
    类与类加载器类加载器阶段的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作被放到了Java虚拟机外部去实现,以便让应用程序自己定义...换言之,比较两个类是否相等,只有在这两个类是同一个类加载器的前
  • 类加载

    2017-05-16 10:09:56
    类加载不同类加载加载,虽然源于同一个class文件,但是无论是equals,isAssignableFrom,isInstance甚至instanceof都会返回false类加载器种类 Bootstrap ClassLoader 启动类加载器,加载\lib下或者被-...
  • 换句话说,在JVM中,即使两个类对象(Class对象)来源于同一个Class文件,被同一个虚拟机加载,但是只要加载它们的ClassLoader实例对象不同,那么这两个Class对象就不相等。 2.类加载器的引用的保存 JVM必须知道...
  • 要实现动态加载一个类(可能会修改该类),一般有两种方法,实例化不同classloader加载,另一种方法是用同一个classloader加载,但类名会修改。用的还是JDK编译工具来编译代码,classloader用自定义的...
  • ClassLoader机制

    2019-06-12 22:03:34
    随便写写,l通过oadClass方法来加载,先看该ClassLoader是否有父类,有则递归调用父类的loadClass...不同加载加载同一个类,两者不相等 package com.company; import java.io.IOException; import java.io....
  • 加载器:实现类加载功能 确定类的唯一性(确定 两个类是否 相等 的依据:是否由同一个类加载加载 若 由同一个类加载加载,则这两个类相等;若 由不同的类加载加载,则这两个类不相等。) 类加载器类型 ...
  • 如果这个时候选择在同一个项目中实现这样的功能,那么通常只能选择更低版本的 jar 包,因为它们通常是向下兼容的,但是这样也往往会失去新版本的一些特性或功能,所以我们需要以扩展的方式引入这些 jar 包,并通过...
  • JVM-类加载

    2021-01-13 12:00:48
    也就是说,要表明两个类是否一样的前提是是否由同一个类加载加载。 双亲委派模型 在虚拟机的角度上看,只有两种不同的类加载器。一种是c++实现的,另一种是java 实现的,独立于jvm 全部继承java.lang.ClassLoader....
  • Java基础——ClassLoader

    千次阅读 热门讨论 2014-11-30 12:05:29
     classloader是通过分层的关联方式来管理运行中使用的类,不同classloader中管理的类是不相同的,或者即便两个类毫无二致(除了路径)也是不同的两个类,通俗的说就是,不同的类加载加载的,即使是同一个类,也...
  • 加载器分类: BootStrapClassLoader:java...同一个ClassLoader中只会存在一个相同的Class对象。 不同ClassLoader加载相同的Class对象,他们之间不能相互转换。 如何打破双亲委派 在加载的阶段。 ...
  • 在JVM中表示两个class对象是否为同一个类对象存在两个必要条件 - 类的完整类名必须一致,包括包名。 - 加载这个类的类加载器(ClassLoader)必须相同。 也就是说,在JVM中,即使这个两个类对象(class对象)来源同...
  • 加载器阶段的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作被放到了Java虚拟机外部去实现,以便让应用程序自己定义...换言之,比较两个类是否相等,只有在这两个类是同一个类加载器的前提下才...
  • JVM:类加载

    2019-09-14 08:02:56
    如果两个类来源于同一个Class文件,只要加载它们的类加载不同,那么这两个类就必定不相等。 启动类加载器(Bootstrap ClassLoader) 使用C++语言实现,是虚拟机自身的一部分;这个类加载器负责将存放在\lib目录...
  • JVM之类加载

    2019-03-06 09:14:08
    类只有被同一个类加载加载才有意义,不然,同一个Class文件被两个不同的类加载加载,这两个类也是不相等的。 双亲委派:在Jvm中只存在两种类加载器,1种是启动类加载器(Bootstrap ClassLoader),由C++语言实现...

空空如也

空空如也

1 2 3 4 5
收藏数 90
精华内容 36
关键字:

不同classloader加载同一个类