最近很多小伙伴都在问什么是JavaClassLoader?和什么是suv汽车这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展android–dalvik.system.BaseDe
最近很多小伙伴都在问什么是Java ClassLoader?和什么是suv汽车这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展android – dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)中的类加载错误?、ClassLoader.loadClass() throws java.lang.ClassNotFoundException、classloader加载class的流程及自定义ClassLoader、Java Class 的热替换 自定义 ClassLoader 加载.class等相关知识,下面开始了哦!
本文目录一览:- 什么是Java ClassLoader?(什么是suv汽车)
- android – dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)中的类加载错误?
- ClassLoader.loadClass() throws java.lang.ClassNotFoundException
- classloader加载class的流程及自定义ClassLoader
- Java Class 的热替换 自定义 ClassLoader 加载.class
什么是Java ClassLoader?(什么是suv汽车)
简单地说,什么是Java ClassLoader?何时使用Java?为什么?
好的,我读了一篇维基文章。ClassLoader加载类。好。因此,如果我包含jar文件并导入,则ClassLoader可以完成这项工作。
我为什么要打扰这个ClassLoader?我从未使用过它,也不知道它的存在。
问题是,为什么ClassLoader类存在?而且,您如何在实践中使用它?(案例存在,我知道。)
答案1
小编典典摘自Sun的这个不错的教程:
动机
用静态编译的编程语言(例如C和C ++)编写的应用程序被编译为本地的,机器特定的指令,并保存为可执行文件。将代码组合成可执行的本机代码的过程称为链接-
将单独编译的代码与共享库代码合并以创建可执行应用程序。在动态编译的编程语言(例如Java)中,这是不同的。在Java中,由Java编译器生成的.class文件将保持原样,直到加载到Java虚拟机(JVM)中为止-
换句话说,链接过程由JVM在运行时执行。将类“按需”加载到JVM中。当加载的类依赖于另一个类时,该类也将被加载。
启动Java应用程序时,要运行的第一个类(或应用程序的入口点)是带有称为main()的公共静态void方法的类。此类通常具有对其他类的引用,并且所有加载引用的类的尝试均由类加载器执行。
为了大致了解这种递归类加载以及类加载的思想,请考虑以下简单类:
public class HelloApp { public static void main(String argv[]) { System.out.println("Aloha! Hello and Bye"); }}
如果您通过指定-
verbose:class命令行选项来运行此类,以便显示正在加载的类,您将获得如下所示的输出。请注意,这只是部分输出,因为列表太长而无法在此处显示。
prmpt>java -verbose:class HelloApp[Opened C:\Program Files\Java\jre1.5.0\lib\rt.jar][Opened C:\Program Files\Java\jre1.5.0\lib\jsse.jar][Opened C:\Program Files\Java\jre1.5.0\lib\jce.jar][Opened C:\Program Files\Java\jre1.5.0\lib\charsets.jar][Loaded java.lang.Object from shared objects file][Loaded java.io.Serializable from shared objects file][Loaded java.lang.Comparable from shared objects file][Loaded java.lang.CharSequence from shared objects file][Loaded java.lang.String from shared objects file][Loaded java.lang.reflect.GenericDeclaration from shared objects file][Loaded java.lang.reflect.Type from shared objects file][Loaded java.lang.reflect.AnnotatedElement from shared objects file][Loaded java.lang.Class from shared objects file][Loaded java.lang.Cloneable from shared objects file][Loaded java.lang.ClassLoader from shared objects file][Loaded java.lang.System from shared objects file][Loaded java.lang.Throwable from shared objects file]...[Loaded java.security.BasicPermissionCollection from shared objects file][Loaded java.security.Principal from shared objects file][Loaded java.security.cert.Certificate from shared objects file][Loaded HelloApp from file:/C:/classes/]Aloha! Hello and Bye[Loaded java.lang.Shutdown from shared objects file][Loaded java.lang.Shutdown$Lock from shared objects file]
如您所见,应用程序类(HelloApp)所需的Java运行时类首先被加载。
Java 2平台中的类加载器
Java编程语言不断发展,使应用程序开发人员的生活每天都变得更加轻松。这是通过提供API来完成的,这些API通过允许您专注于业务逻辑而不是基本机制的实现细节来简化您的生活。为了反映Java平台的成熟,最近将J2SE
1.5更改为J2SE 5.0可以证明这一点。
从JDK
1.2开始,JVM内置的引导类加载器负责加载Java运行时的类。该类加载器仅加载在引导类路径中找到的类,并且由于它们是受信任的类,因此不会像对不信任的类那样执行验证过程。除了引导类加载器之外,JVM还具有扩展类加载器,用于从标准扩展API加载类,以及系统类加载器,用于从常规类路径以及应用程序类加载类。
由于有多个类加载器,因此它们在树中表示,其根是引导类加载器。每个类加载器都有对其父类加载器的引用。当要求类加载器加载类时,它会在尝试加载项目本身之前先咨询其父类加载器。父级依次咨询其父级,依此类推。因此,只有在所有祖先类加载器都找不到该类后,当前类加载器才涉及。换句话说,使用了委托模型。
java.lang.ClassLoader类
的java.lang.ClassLoader
是,可以由需要延长在其中JVM动态加载类的方式应用作为子类的抽象类。java.lang.ClassLoader
实例化新的类加载器时,(及其子类)中的构造函数允许您指定父级。如果您未明确指定父级,则会将虚拟机的系统类加载器指定为默认父级。换句话说,ClassLoader类使用委托模型来搜索类和资源。因此,ClassLoader的每个实例都有一个关联的父类加载器,因此当请求查找类或资源时,在尝试查找该类或资源本身之前,将任务委派给其父类加载器。loadClass()
当调用ClassLoader
的方法以加载类时,它按顺序执行以下任务:
如果已经加载了一个类,它将返回它。否则,它将对新类的搜索委托给父类加载器。如果父类加载器找不到该类,则loadClass()
调用该方法findClass()
以查找和加载该类。finalClass()
如果父类加载器找不到该类,则该方法在当前类加载器中搜索该类。
原始文章中还有更多内容,它还向您展示了如何实现自己的网络类加载器,它回答了有关原因(以及如何)的问题。另请参阅API文档。
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
解决方法
ClassLoader.loadClass() throws java.lang.ClassNotFoundException
今天写一个 RMI 的应用,气死人了,弄半天,跑到 sun 官网去一看,告诉我是一个 BUG, 我流出了鼻血。
ToWork:
-Dsun.lang.ClassLoader.allowArraySyntax=true
点击打开链接
原文链接: http://blog.csdn.net/chengchanglun/article/details/7441034
classloader加载class的流程及自定义ClassLoader
java应用环境中不同的class分别由不同的ClassLoader负责加载。
一个jvm中默认的classloader有Bootstrap ClassLoader、Extension ClassLoader、App ClassLoader,分别各司其职:
- Bootstrap ClassLoader 负责加载java基础类,主要是 %JRE_HOME/lib/ 目录下的rt.jar、resources.jar、charsets.jar和class等
- Extension ClassLoader 负责加载java扩展类,主要是 %JRE_HOME/lib/ext 目录下的jar和class
- App ClassLoader 负责加载当前java应用的classpath中的所有类。
其中Bootstrap ClassLoader是JVM级别的,由C++撰写;Extension ClassLoader、App ClassLoader都是java类,都继承自URLClassLoader超类。
Bootstrap ClassLoader由JVM启动,然后初始化sun.misc.Launcher ,sun.misc.Launcher初始化Extension ClassLoader、App ClassLoader。
类加载器的双亲委派加载机制(重点):当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父类去完成,每一个层次类加载器都是如此,因此所有的加载请求都应该传送到启动类加载其中,只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径下没有找到所需加载的Class),子类加载器才会尝试自己去加载。
Bootstrap ClassLoader、Extension ClassLoader、App ClassLoader三者的关系如下:
Bootstrap ClassLoader是Extension ClassLoader的parent,Extension ClassLoader是App ClassLoader的parent。
但是这并不是继承关系,只是语义上的定义,基本上,每一个ClassLoader实现,都有一个Parent ClassLoader。
可以通过ClassLoader的getParent方法得到当前ClassLoader的parent。Bootstrap ClassLoader比较特殊,因为它不是java class所以Extension ClassLoader的getParent方法返回的是NULL。
了解了ClassLoader的原理和流程以后,我们可以试试自定义ClassLoader。
关于自定义ClassLoader:
由于一些特殊的需求,我们可能需要定制ClassLoader的加载行为,这时候就需要自定义ClassLoader了.
自定义ClassLoader需要继承ClassLoader抽象类,重写findClass方法,这个方法定义了ClassLoader查找class的方式。
主要可以扩展的方法有:
findClass 定义查找Class的方式
defineClass 将类文件字节码加载为jvm中的class
findResource 定义查找资源的方式
如果嫌麻烦的话,我们可以直接使用或继承已有的ClassLoader实现,比如
java.net.URLClassLoader
java.security.SecureClassLoader
java.rmi.server.RMIClassLoader
sun.applet.AppletClassLoader
Extension ClassLoader 和 App ClassLoader都是java.net.URLClassLoader的子类。
这个是URLClassLoader的构造方法:
public URLClassLoader(URL[] urls, ClassLoader parent)
public URLClassLoader(URL[] urls)
urls参数是需要加载的ClassPath url数组,可以指定parent ClassLoader,不指定的话默认以当前调用类的ClassLoader为parent。
代码示例:
ClassLoader classLoader = new URLClassLoader(urls);
Thread.currentThread().setContextClassLoader(classLoader);
Class clazz=classLoader.loadClass("com.company.MyClass");//使用loadClass方法加载class,这个class是在urls参数指定的classpath下边。
Method taskMethod = clazz.getMethod("doTask", String.class, String.class);//然后我们就可以用反射做些事情了
taskMethod.invoke(clazz.newInstance(),"hello","world");
由于classloader 加载类用的是全盘负责委托机制。所谓全盘负责,即是当一个classloader加载一个Class的时候,这个Class所依赖的和引用的所有 Class也由这个classloader负责载入,除非是显式的使用另外一个classloader载入。
所以,当我们自定义的classloader加载成功了com.company.MyClass以后,MyClass里所有依赖的class都由这个classLoader来加载完成。
自定义ClassLoader在某些应用场景还是比较适用,特别是需要灵活地动态加载class的时候。
Java Class 的热替换 自定义 ClassLoader 加载.class
本文是 java 热替换的实验,参考了Java 类的热替换 —— 概念、设计与实现 http://www.ibm.com/developerworks/cn/java/j-lo-hotswapcls/index.html
classloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
这个语句只适用于加载.jar
如果加载.class 的话需要使用自定义的 ClassLoader
package yerasel;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashSet;
/*
* 实现热部署,自定义ClassLoader,加载的是.class
*/
class HowswapCL extends ClassLoader {
private String basedir; // 需要该类加载器直接加载的类文件的基目录
private HashSet dynaclazns; // 需要由该类加载器直接加载的类名
public HowswapCL(String basedir, String[] clazns) {
super(null); // 指定父类加载器为 null
this.basedir = basedir;
dynaclazns = new HashSet();
loadClassByMe(clazns);
}
private void loadClassByMe(String[] clazns) {
for (int i = 0; i < clazns.length; i++) {
loadDirectly(clazns[i]);
dynaclazns.add(clazns[i]);
}
}
private Class loadDirectly(String name) {
Class cls = null;
StringBuffer sb = new StringBuffer(basedir);
String classname = name.replace(''.'', File.separatorChar) + ".class";
sb.append(File.separator + classname);
File classF = new File(sb.toString());
try {
cls = instantiateClass(name, new FileInputStream(classF),
classF.length());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return cls;
}
private Class instantiateClass(String name, InputStream fin, long len) {
byte[] raw = new byte[(int) len];
try {
fin.read(raw);
fin.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return defineClass(name, raw, 0, raw.length);
}
protected Class loadClass(String name, boolean resolve)
throws ClassNotFoundException {
Class cls = null;
cls = findLoadedClass(name);
if (!this.dynaclazns.contains(name) && cls == null)
cls = getSystemClassLoader().loadClass(name);
if (cls == null)
throw new ClassNotFoundException(name);
if (resolve)
resolveClass(cls);
return cls;
}
}
/*
* 每隔500ms运行一次,不断加载class
*/
class Multirun implements Runnable {
public void run() {
try {
while (true) {
// 每次都创建出一个新的类加载器
// class需要放在自己package名字的文件夹下
String url = System.getProperty("user.dir") + "/lib";// "/lib/yerasel/GetPI.jar";
HowswapCL cl = new HowswapCL(url,
new String[] { "yerasel.GetPI" });
Class cls = cl.loadClass("yerasel.GetPI");
Object foo = cls.newInstance();
// 被调用函数的参数
Method m = foo.getClass().getMethod("Output", new Class[] {});
m.invoke(foo, new Object[] {});
Thread.sleep(500);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
public class Test {
public static Method initAddMethod() {
try {
Method add = URLClassLoader.class.getDeclaredMethod("addURL",
new Class[] { URL.class });
add.setAccessible(true);
return add;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
// 热部署测试代码
Thread t;
t = new Thread(new Multirun());
t.start();
}
}
GetPI.java 内容:
package yerasel;
import java.io.PrintStream;
public class GetPI
{
public static double Darts(int n)
{
int k = 0;
double x = 0.0D;
double y = 0.0D;
for (int i = 0; i < n; i++)
{
x = Math.random();
y = Math.random();
if (x * x + y * y <= 1.0D)
k++;
}
return 4 * k / n;
}
// 本热部署实验中,上面的Darts函数没有用到,请忽略
public static void Output() {
System.out.println("Output");
}
}
另一个 GetPI.java 只在输出时候改为 aaaOutput
生成 jar 包的命令
jar cvf GetPI.jar GetPI.class
一定要注意的是:class 需要放在 package 名字的文件夹下
本文中.class 放在 /lib (自定义路径)/yerasel (package 名字) 下。
运行时候,程序加载指定文件夹下的.class,即开始输出 aaaOutput,然后手动将另外一个.class (输出 Output 的.class) 覆盖此文件,
程序立即开始输出 Output
运行结果图:
今天的关于什么是Java ClassLoader?和什么是suv汽车的分享已经结束,谢谢您的关注,如果想了解更多关于android – dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)中的类加载错误?、ClassLoader.loadClass() throws java.lang.ClassNotFoundException、classloader加载class的流程及自定义ClassLoader、Java Class 的热替换 自定义 ClassLoader 加载.class的相关知识,请在本站进行查询。
本文标签: