GVKun编程网logo

Class 、ClassLoader 加载资源(classloader加载过程)

17

本文的目的是介绍Class、ClassLoader加载资源的详细情况,特别关注classloader加载过程的相关信息。我们将通过专业的研究、有关数据的分析等多种方式,为您呈现一个全面的了解Class

本文的目的是介绍Class 、ClassLoader 加载资源的详细情况,特别关注classloader加载过程的相关信息。我们将通过专业的研究、有关数据的分析等多种方式,为您呈现一个全面的了解Class 、ClassLoader 加载资源的机会,同时也不会遗漏关于android – dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)中的类加载错误?、Class.forName () 和 ClassLoader.loadClass () 的区别?、Class.forName 和 ClassLoader.loadClass、Class.forName 和 classLoader.loadClass 的比较的知识。

本文目录一览:

Class 、ClassLoader 加载资源(classloader加载过程)

Class 、ClassLoader 加载资源(classloader加载过程)


Class 的 getResource 方法,通过ClassLoader实现:

注意参数格式,可以是绝对路径(在 类路径 变量指定的目录下或jar中 查找) 也可以是相对路径相对当前类的类文件包名

resolveName(..)方法将输入的资源名转化为 类路径 下的文件名。

通过该方法可知,除了使用Class加载资源文件外,也可以直接通过ClassLoader加载资源文件,把资源文件当成 一个普通的 类文件 就可以了,只是这时候的 package name 需要把 ''.'' 变成 ''/''

/**
     * Finds a resource with a given name.  The rules for searching resources
     * associated with a given class are implemented by the defining
     * {@linkplain ClassLoader class loader} of the class.  This method
     * delegates to this object''s class loader.  If this object was loaded by
     * the bootstrap class loader, the method delegates to {@link
     * ClassLoader#getSystemResource}.
     *
     * <p> Before delegation, an absolute resource name is constructed from the
     * given resource name using this algorithm:
     *
     * <ul>
     *
     * <li> If the {@code name} begins with a {@code ''/''}
     * (<tt>''&#92;u002f''</tt>), then the absolute name of the resource is the
     * portion of the {@code name} following the {@code ''/''}.
     *
     * <li> Otherwise, the absolute name is of the following form:
     *
     * <blockquote>
     *   {@code modified_package_name/name}
     * </blockquote>
     *
     * <p> Where the {@code modified_package_name} is the package name of this
     * object with {@code ''/''} substituted for {@code ''.''}
     * (<tt>''&#92;u002e''</tt>).
     *
     * </ul>
     *
     * @param  name name of the desired resource
     * @return      A  {@link java.net.URL} object or {@code null} if no
     *              resource with this name is found
     * @since  JDK1.1
     */
    public java.net.URL getResource(String name) {
        name = resolveName(name);
        ClassLoader cl = getClassLoader0();
        if (cl==null) {
            // A system class.
            return ClassLoader.getSystemResource(name);
        }
        return cl.getResource(name);
    }

ClassLoader 的getResource方法:

实现的自己的ClassLoader时,可以复写findResource方法在特定的位置查找资源,默认在在 类路径 下查找,就像查找 类文件一样

/**
     * Finds the resource with the given name.  A resource is some data
     * (images, audio, text, etc) that can be accessed by class code in a way
     * that is independent of the location of the code.
     *
     * <p> The name of a resource is a ''<tt>/</tt>''-separated path name that
     * identifies the resource.
     *
     * <p> This method will first search the parent class loader for the
     * resource; if the parent is <tt>null</tt> the path of the class loader
     * built-in to the virtual machine is searched.  That failing, this method
     * will invoke {@link #findResource(String)} to find the resource.  </p>
     *
     * @param  name
     *         The resource name
     *
     * @return  A <tt>URL</tt> object for reading the resource, or
     *          <tt>null</tt> if the resource could not be found or the invoker
     *          doesn''t have adequate  privileges to get the resource.
     *
     * @since  1.1
     */
    public URL getResource(String name) {
        URL url;
        if (parent != null) {
            url = parent.getResource(name);
        } else {
            url = getBootstrapResource(name);
        }
        if (url == null) {
            url = findResource(name);
        }
        return url;
    }
    
    
     /**
     * Find a resource of the specified name from the search path used to load
     * classes.  This method locates the resource through the system class
     * loader (see {@link #getSystemClassLoader()}).  </p>
     *
     * @param  name
     *         The resource name
     *
     * @return  A {@link java.net.URL <tt>URL</tt>} object for reading the
     *          resource, or <tt>null</tt> if the resource could not be found
     *
     * @since  1.1
     */
    public static URL getSystemResource(String name) {
        ClassLoader system = getSystemClassLoader();
        if (system == null) {
            return getBootstrapResource(name);
        }
        return system.getResource(name);
    }
    
    
    
    /**
     * Returns an enumeration of {@link java.net.URL <tt>URL</tt>} objects
     * representing all the resources with the given name. Class loader
     * implementations should override this method to specify where to load
     * resources from.  </p>
     *
     * @param  name
     *         The resource name
     *
     * @return  An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
     *          the resources
     *
     * @throws  IOException
     *          If I/O errors occur
     *
     * @since  1.2
     */
    protected Enumeration<URL> findResources(String name) throws IOException {
        return java.util.Collections.emptyEnumeration();
    }


ClassLoader:

loadClass 、loadLibrary:

   

findClass、findLibray、findResource:


下面是一个例子:

package test;

import java.net.URL;

public class LoadResourceByClassLoader {

	public static void main(String[] args){
		LoadResource lr = new LoadResource();
		lr.load();
	}
}

class LoadResource{
	public void load(){
		ClassLoader cl = this.getClass().getClassLoader();
		
		String name = resolveName("/abs.txt");
		URL aurl = cl.getResource(name);
		System.out.println(aurl != null? "resource url:" + aurl.toString(): "/abs.txt is null");
		
		name = resolveName("abs.txt");
		aurl = cl.getResource(name);
		System.out.println(aurl != null? "resource url:" + aurl.toString(): "abs.txt is null");
		
		name = resolveName("relative.txt");
		URL rurl = cl.getResource(name);
		System.out.println(rurl != null? "resource url:" + rurl.toString(): "relative.txt is null");
		
		name = resolveName("d/relative.txt");
		rurl = cl.getResource(name);
		System.out.println(rurl != null? "resource url:" + rurl.toString(): "relative.txt is null");
		
	}
	
	
	/**
	 * Copied from Class.java
	 * 
     * Add a package name prefix if the name is not absolute Remove leading "/"
     * if name is absolute
     */
    private String resolveName(String name) {
    	System.out.println( "befor resolving: " + name );
        if (name == null) {
            return name;
        }
        if (!name.startsWith("/")) {
            Class<?> c = this.getClass();
            while (c.isArray()) {
                c = c.getComponentType();
            }
            String baseName = c.getName();
            int index = baseName.lastIndexOf(''.'');
            if (index != -1) {
                name = baseName.substring(0, index).replace(''.'', ''/'')
                    +"/"+name;
            }
        } else {
            name = name.substring(1);
        }
        
        System.out.println(" after resolving: " +name );
        return name;
    }

}

输出:

befor resolving: /abs.txt

 after resolving: abs.txt

resource url:file:/Users/may/Documents/workspace/TESTcore/bin/abs.txt


befor resolving: abs.txt

 after resolving: test/abs.txt

abs.txt is null


befor resolving: relative.txt

 after resolving: test/relative.txt

resource url:file:/Users/may/Documents/workspace/TESTcore/bin/test/relative.txt


befor resolving: d/relative.txt

 after resolving: test/d/relative.txt

resource url:file:/Users/may/Documents/workspace/TESTcore/bin/test/d/relative.txt


android – dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)中的类加载错误?

android – dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)中的类加载错误?

无法运行以下项目,项目中没有错误.我已经多次运行该项目了.请有人帮我解决问题.

AndroidManifest.xml中:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.extremefitness.org"
    android:versionCode="1"
    android:versionName="1.0" >

    <supports-screens
        android:anyDensity="false"
        android:largeScreens="true"
        android:normalScreens="true"
        android:smallScreens="true"
        android:xlargeScreens="true" />

    <uses-permission android:name="android.permission.INTERNET" >
    </uses-permission>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >
    </uses-permission>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" >
    </uses-permission>
    <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
    <uses-permission android:name="android.permission.CLEAR_APP_CACHE" >
    </uses-permission>
    <uses-permission android:name="android.permission.disABLE_KEyguard" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".Tabbaractivity"
            android:windowSoftInputMode="adjustPan|adjustResize" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".HomeActivity"
            android:screenorientation="portrait"
            android:windowSoftInputMode="adjustPan|adjustResize" >
        </activity>
        <activity
            android:name="com.extremefitness.views.LoginActivity"
            android:noHistory="true"
            android:screenorientation="portrait"
            android:windowSoftInputMode="adjustPan|adjustResize" >
        </activity>
        <activity
            android:name="com.extremefitness.views.Registeractivity"
            android:noHistory="true"
            android:screenorientation="portrait"
            android:windowSoftInputMode="adjustPan|adjustResize" >
        </activity>
        <activity
            android:name="com.extremefitness.views.Profiletabactivity"
            android:screenorientation="portrait"
            android:windowSoftInputMode="adjustPan|adjustResize" >
        </activity>
        <activity
            android:name="com.extremefitness.views.RandomWorkouttabactivity"
            android:screenorientation="portrait"
            android:windowSoftInputMode="adjustPan|adjustResize" >
        </activity>
        <activity
            android:name="com.extremefitness.views.Tracktabactivity"
            android:screenorientation="portrait"
            android:windowSoftInputMode="adjustPan|adjustResize" >
        </activity>
        <activity
            android:name="com.extremefitness.views.Workouttabactivity"
            android:screenorientation="portrait"
            android:windowSoftInputMode="adjustPan|adjustResize" >
        </activity>
        <activity
            android:name="com.extremefitness.views.StatsActivity"
            android:screenorientation="portrait"
            android:windowSoftInputMode="adjustPan|adjustResize" >
        </activity>
        <activity
            android:name="com.extremefitness.views.ExerciseActivity"
            android:screenorientation="portrait"
            android:windowSoftInputMode="adjustPan|adjustResize" >
        </activity>
        <activity
            android:name="com.extremefitness.views.CustomDialog"
            android:screenorientation="portrait"
            android:windowSoftInputMode="adjustPan|adjustResize" >
        </activity>
        <activity
            android:name="com.extremefitness.views.WorkoutDescription"
            android:noHistory="true"
            android:screenorientation="portrait"
            android:windowSoftInputMode="adjustPan|adjustResize" >
        </activity>
        <activity
            android:name="com.extremefitness.views.ExerciseDescription"
            android:screenorientation="portrait"
            android:windowSoftInputMode="adjustPan|adjustResize" >
        </activity>
        <activity
            android:name="com.extremefitness.views.Settings"
            android:screenorientation="portrait"
            android:windowSoftInputMode="adjustPan|adjustResize" >
        </activity>

        <activity
            android:name="com.extremefitness.views.RandomWorkoutResponse"
            android:screenorientation="portrait"
            android:windowSoftInputMode="adjustPan|adjustResize" >
        </activity>
        <activity
            android:name=".FBActivity"
            android:screenorientation="portrait"
            android:windowSoftInputMode="adjustPan|adjustResize" >
        </activity>
        <activity
            android:name=".Twitteractivity"
            android:screenorientation="portrait"
            android:windowSoftInputMode="adjustPan|adjustResize" >
        </activity>
        <activity
            android:name="com.extremefitness.views.VideoDialog"
            android:configChanges="orientation|screenSize|keyboardHidden"
            android:screenorientation="nosensor" >
            <Meta-data
                android:name="@string/minVersion"
                android:value="8" />
            <Meta-data
                android:name="@string/isLaunchableActivity"
                android:value="true" />
        </activity>
        <activity
            android:name="com.extremefitness.views.WorktVideoDialog"
            android:configChanges="orientation|screenSize|keyboardHidden"
            android:screenorientation="nosensor" >
            <Meta-data
                android:name="@string/minVersion"
                android:value="8" />
            <Meta-data
                android:name="@string/isLaunchableActivity"
                android:value="true" />
        </activity>
    </application>

</manifest>

错误的日志:

04-26 14:45:08.211: E/AndroidRuntime(2179): FATAL EXCEPTION: main
04-26 14:45:08.211: E/AndroidRuntime(2179): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.extremefitness.org/com.extremefitness.org.Tabbaractivity}: java.lang.classNotFoundException: com.extremefitness.org.Tabbaractivity
04-26 14:45:08.211: E/AndroidRuntime(2179):     at android.app.ActivityThread.performlaunchActivity(ActivityThread.java:1894)
04-26 14:45:08.211: E/AndroidRuntime(2179):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1995)
04-26 14:45:08.211: E/AndroidRuntime(2179):     at android.app.ActivityThread.access$600(ActivityThread.java:128)
04-26 14:45:08.211: E/AndroidRuntime(2179):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1161)
04-26 14:45:08.211: E/AndroidRuntime(2179):     at android.os.Handler.dispatchMessage(Handler.java:99)
04-26 14:45:08.211: E/AndroidRuntime(2179):     at android.os.Looper.loop(Looper.java:137)
04-26 14:45:08.211: E/AndroidRuntime(2179):     at android.app.ActivityThread.main(ActivityThread.java:4517)
04-26 14:45:08.211: E/AndroidRuntime(2179):     at java.lang.reflect.Method.invokeNative(Native Method)
04-26 14:45:08.211: E/AndroidRuntime(2179):     at java.lang.reflect.Method.invoke(Method.java:511)
04-26 14:45:08.211: E/AndroidRuntime(2179):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:993)
04-26 14:45:08.211: E/AndroidRuntime(2179):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:760)
04-26 14:45:08.211: E/AndroidRuntime(2179):     at dalvik.system.NativeStart.main(Native Method)
04-26 14:45:08.211: E/AndroidRuntime(2179): Caused by: java.lang.classNotFoundException: com.extremefitness.org.Tabbaractivity
04-26 14:45:08.211: E/AndroidRuntime(2179):     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)
04-26 14:45:08.211: E/AndroidRuntime(2179):     at java.lang.classLoader.loadClass(ClassLoader.java:501)
04-26 14:45:08.211: E/AndroidRuntime(2179):     at java.lang.classLoader.loadClass(ClassLoader.java:461)
04-26 14:45:08.211: E/AndroidRuntime(2179):     at android.app.Instrumentation.newActivity(Instrumentation.java:1027)
04-26 14:45:08.211: E/AndroidRuntime(2179):     at android.app.ActivityThread.performlaunchActivity(ActivityThread.java:1885)
04-26 14:45:08.211: E/AndroidRuntime(2179):     ... 11 more

解决方法

我遇到同样的问题,检查构建路径,你的第三个罐子没有在你的apk文件中. 1.右键单击您的项目,选择“构建路径” – > “配置构建路径…”. 2.在“订购和导出”选项卡中,选中“Android私有库”选项. 希望工作.

Class.forName () 和 ClassLoader.loadClass () 的区别?

Class.forName () 和 ClassLoader.loadClass () 的区别?

Class.forName() ClassLoader.loadClass() 的区别 ?

Class.forName() Class.forName().NewInstance() 的区别 ?

Class.forName("xx.xx") 等同于 Class.forName("xx.xx",true,CALLClass.class.getClassLoader()),第二个参数 (boolean) 表示装载类的时候是否初始化该类,即调用类的静态块的语句及初始化静态成员变量。

ClassLoader loader = Thread.currentThread.getContextClassLoader(); // 也可以用 (ClassLoader.getSystemClassLoader())

Class cls = loader.loadClass("xx.xx"); // 这句话没有执行初始化,其实与 Class.forName("xx.xx"falseloader) 是一致的,只是 loader.loadClass("xx.xx") 执行的是更底层的操作。

只有执行 cls.NewInstance() 才能够初始化类,得到该类的一个实例

 

 

Class 的装载分了三个阶段,loadinglinking initializing,分别定义在 The Java Language Specification 12.212.3 12.4
Class.forName(className)
实际上是调用 Class.forName(className, true, this.getClass().getClassLoader())。注意第二个参数,是指 Class loading 后是不是必须被初始化。
ClassLoader.loadClass(className)
实际上调用的是 ClassLoader.loadClass(name, false),第二个参数指出 Class 是否被 link

区别就出来了。Class.forName(className) 装载的 class 已经被初始化,而 ClassLoader.loadClass(className) 装载的 class 还没有被 link
一般情况下,这两个方法效果一样,都能装载 Class。但如果程序依赖于 Class 是否被初始化,就必须用 Class.forName(name) 了。
例 如,在 JDBC 编程中,常看到这样的用法,Class.forName("com.mysql.jdbc.Driver"),如果换成了 getClass().getClassLoader().loadClass("com.mysql.jdbc.Driver"),就不行。
为什么呢?打开 com.mysql.jdbc.Driver 的源代码看看,
//
// Register ourselves with the DriverManager
//
static {
    try {
        java.sql.DriverManager.registerDriver(new Driver());
    } catch (SQLException E) {
        throw new RuntimeException("Can''t register driver!");
    }
}

原来,Driver static 块中会注册自己到 java.sql.DriverManager。而 static 块就是在 Class 的初始化中被执行。所以这个地方就只能用 Class.forName(className)

Class.forName 和 ClassLoader.loadClass

Class.forName 和 ClassLoader.loadClass

Class.forName("xx.xx")
//等同于
Class.forName("xx.xx",true,this.getClass.getClassLoader())
//第二个参数(bool)表示装载类的时候是否初始化该类,即调用类的静态块的语句及初始化静态成员变量。

ClassLoader loader = Thread.currentThread.getContextClassLoader();
//也可以用
(ClassLoader.getSystemClassLoader()) Class cls = loader.loadClass("xx.xx"); 
//这句话没有执行初始化,其实与Class.forName("xx.xx",false,loader)是一致的,
//只是loader.loadClass("xx.xx")执行的是更底层的操作。

    只有执行 cls.NewInstance () 才能够初始化类, 得到该类的一个实例 Class 的装载分了三个阶段,loading,linking 和 initializing, 分别定义在 The Java Language Specification 的 12.2,12.3 和 12.4。

    Class.forName (className) 实际上是调用 Class.forName (className, true, this.getClass ().getClassLoader ())。 注意第二个参数,是指 Class 被 loading 后是不是必须被初始化。

    ClassLoader.loadClass (className) 实际上调用的是 ClassLoader.loadClass (name, false), 第二个参数指出 Class 是否被 link。

    区别就出来了。 Class.forName (className) 装载的 class 已经被初始化, 而 ClassLoader.loadClass (className) 装载的 class 还没有被 link。

    forName 支持数组类型,loadClass 不支持数组

    一般情况下,这两个方法效果一样,都能装载 Class。 但如果程序依赖于 Class 是否被初始化,就必须用 Class.forName (name) 了。

     例如,在 JDBC 编程中,常看到这样的用法,Class.forName ("com.mysql.jdbc.Driver"), 如果换成了 getClass ().getClassLoader ().loadClass ("com.mysql.jdbc.Driver"),就不行。 为什么呢?打开 com.mysql.jdbc.Driver 的源代码看看,

//Register ourselves with the DriverManager
static { 
   try { 
      java.sql.DriverManager.registerDriver(new Driver()); 
   } catch (SQLException E) { 
      throw new RuntimeException("Can''t register driver!"); 
   } 
}

原来,Driver 在 static 块中会注册自己到 java.sql.DriverManager。而 static 块就是在 Class 的初始化中被执行。所以这个地方就只能用 Class.forName (className)。

Class.forName 和 classLoader.loadClass 的比较

Class.forName 和 classLoader.loadClass 的比较

Class.forName 和 ClassLoader.loadClass 的比较

简述:
Class.forName(String className)使用装载当前类的类装载器来装载指定类。在 class.forName (String className) 方法内部调用了 Class.forName (className,true, this.getClass ().getClassLoader ()) 方法,如你所见,第三个参数就是指定类装载器,显而易见,它调用的是装载当前类的类装载器实例(也就是 this.getClass ().getClassLoader ());
classLoader.loadClass (StringclassName , boolean resolve) 需要手动 new 一个类装载器实例,再去 loadClass。
所以这两种类装载方式的区别之一就是一个默认通过当前类实例的类装载器来装载指定类,而另一个则需要手动 new 一个类装载器实例再去装载指定类。

分析:
Class 的装载分了三个阶段,loading,linking 和 initializing,分别定义在 The Java Language Specification 的 12.2,12.3 和 12.4。
Class.forName (className) 实际上是调用 Class.forName (className, true, this.getClass ().getClassLoader ())。注意第二个参数,是指 Class 被 loading 后是不是必须被初始化。
ClassLoader.loadClass (className) 实际上调用的是 ClassLoader.loadClass (name, false),第二个参数指出 Class 是否被 link。
区别就出来了。Class.forName (className) 装载的 class 已经被初始化,而 ClassLoader.loadClass (className) 装载的 class 还没有被 link,就更加谈不上初始化了。
一般情况下,这两个方法效果一样,都能装载 Class。但如果程序依赖于 Class 是否被初始化,就必须用 Class.forName (name) 了。
例如,在 JDBC 编程中,常看到这样的用法,Class.forName ("com.mysql.jdbc.Driver"),如果换成了 getClass ().getClassLoader ().loadClass ("com.mysql.jdbc.Driver"),就不行。
为什么呢?打开 com.mysql.jdbc.Driver 的源代码看看,
//
// Register ourselves with the DriverManager
//
static {
    try {
        java.sql.DriverManager.registerDriver(new Driver());
    } catch (SQLException E) {
        throw new RuntimeException("Can''t register driver!");
    }
}
原来,Driver 在 static 块中会注册自己到 java.sql.DriverManager。而 static 块就是在 Class 的初始化中被执行。所以这个地方就只能用 Class.forName (className)。

关于Class 、ClassLoader 加载资源classloader加载过程的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于android – dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)中的类加载错误?、Class.forName () 和 ClassLoader.loadClass () 的区别?、Class.forName 和 ClassLoader.loadClass、Class.forName 和 classLoader.loadClass 的比较的相关知识,请在本站寻找。

本文标签: