- 浏览: 354222 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
无红墙:
另一种修改,请参考:https://github.com/ta ...
Dubbo不能优雅停机,导致停止服务的时候,业务掉单 -
fish_no7:
if (handler instanceof WrappedC ...
Dubbo不能优雅停机,导致停止服务的时候,业务掉单 -
frankfan915:
lizhou828 写道怎么解决?设置NetTimeoutFo ...
Communications link failure错误分析 -
lizhou828:
怎么解决?
Communications link failure错误分析 -
frankfan915:
ileson 写道 解决办法sh设置NetTimeoutFo ...
Communications link failure错误分析
最近本来打算研究分布式的东西的,看了一位大侠写的分布式系统,其中要实现把class传到客户端,然后在客户端实例化的工作,就去研究了一下ClassLoader的原理。
准备工作:http://download.java.net/openjdk/jdk6/
压缩包中含有 Windows, Linux, Solaris 平台 JRE 源代码、JVM 源代码,以及 JDK 中类库和工具的源代码。
有了源代码就可以查看源码分析了。
JVM自带的类加载器可以分为三类:Boot Start ClassLoader,Ext ClassLoader, App ClassLoader
1. Boot Start ClassLoader其实不是一个类,其实就是直接由JVM自身来加载,因此当类如果是Boot Start ClassLoader加载的话,就会返回null。
public static void getBootStartClass() { URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs(); for (int i = 0; i < urls.length; i++) { System.out.println(urls[i]); } }
从运行结果可以看到加载的都是Java/jdk1.6.0_23/jre/lib/下面的jar包
2.Boot Start ClassLoader会加载sun.misc.Launcher类。其中Lancherer调用ExtClassLoader.getExtClassLoader();生成ExtClassLoader。可见下面源代码
public Launcher() { // Create the extension class loader ClassLoader extcl; try { extcl = ExtClassLoader.getExtClassLoader(); } catch (IOException e) { throw new InternalError( "Could not create extension class loader"); } // Now create the class loader to use to launch the application try { loader = AppClassLoader.getAppClassLoader(extcl); } catch (IOException e) { throw new InternalError( "Could not create application class loader"); } // Also set the context class loader for the primordial thread. Thread.currentThread().setContextClassLoader(loader); // Finally, install a security manager if requested String s = System.getProperty("java.security.manager"); if (s != null) { SecurityManager sm = null; if ("".equals(s) || "default".equals(s)) { sm = new java.lang.SecurityManager(); } else { try { sm = (SecurityManager)loader.loadClass(s).newInstance(); } catch (IllegalAccessException e) { } catch (InstantiationException e) { } catch (ClassNotFoundException e) { } catch (ClassCastException e) { } } if (sm != null) { System.setSecurityManager(sm); } else { throw new InternalError( "Could not create SecurityManager: " + s); } } }
接下来我们看一下ExtClassLoader 类的源代码,可以看到继承了URLClassLoader类,加载的路径是系统属性java.ext.dirs。打印出来为:jdk1.6.0_23\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext
static class ExtClassLoader extends URLClassLoader { private File[] dirs; /** * create an ExtClassLoader. The ExtClassLoader is created * within a context that limits which files it can read */ public static ExtClassLoader getExtClassLoader() throws IOException { final File[] dirs = getExtDirs(); try { // Prior implementations of this doPrivileged() block supplied // aa synthesized ACC via a call to the private method // ExtClassLoader.getContext(). return (ExtClassLoader) AccessController.doPrivileged( new PrivilegedExceptionAction() { public Object run() throws IOException { int len = dirs.length; for (int i = 0; i < len; i++) { MetaIndex.registerDirectory(dirs[i]); } return new ExtClassLoader(dirs); } }); } catch (java.security.PrivilegedActionException e) { throw (IOException) e.getException(); } } void addExtURL(URL url) { super.addURL(url); } /* * Creates a new ExtClassLoader for the specified directories. */ public ExtClassLoader(File[] dirs) throws IOException { super(getExtURLs(dirs), null, factory); this.dirs = dirs; } private static File[] getExtDirs() { String s = System.getProperty("java.ext.dirs"); File[] dirs; if (s != null) { StringTokenizer st = new StringTokenizer(s, File.pathSeparator); int count = st.countTokens(); dirs = new File[count]; for (int i = 0; i < count; i++) { dirs[i] = new File(st.nextToken()); } } else { dirs = new File[0]; } return dirs; } }
再看看APP ClassLoader,也继承了URLClassLoader。加载的路径是系统属性java.ext.dirs
static class AppClassLoader extends URLClassLoader { public static ClassLoader getAppClassLoader(final ClassLoader extcl) throws IOException { final String s = System.getProperty("java.class.path"); final File[] path = (s == null) ? new File[0] : getClassPath(s); // Note: on bugid 4256530 // Prior implementations of this doPrivileged() block supplied // a rather restrictive ACC via a call to the private method // AppClassLoader.getContext(). This proved overly restrictive // when loading classes. Specifically it prevent // accessClassInPackage.sun.* grants from being honored. // return (AppClassLoader) AccessController.doPrivileged(new PrivilegedAction() { public Object run() { URL[] urls = (s == null) ? new URL[0] : pathToURLs(path); return new AppClassLoader(urls, extcl); } }); } }
既然有那么多加载器,那么它们的加载顺序是怎么样的呢?从下面的代码可以看到当加载类的时候,会先看一下当前类是不是已经被加载了,如果加载了就返回。如果没,就调用父类的加载器来加载类。如果父类的类加载器是null就调用bootsttap classloader来加载。这就是父类委托,因此在加载的时候是先从bootsttap classloader开始查找,一层层往下找。
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { // First, check if the class has already been loaded Class c = findLoadedClass(name); if (c == null) { try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClass0(name); } } catch (ClassNotFoundException e) { // If still not found, then invoke findClass in order // to find the class. c = findClass(name); } } if (resolve) { resolveClass(c); } return c; }
看了那么多源代码那么怎么实现自己的classloader呢,有什么作用呢,对于一些我们不想被反编译的类,我们可以调用加密技术将类加密。在使用的时候只要用自定义的classloader反编译就好了。
我们可以通过两种方法来写自己的classloader,下面分别来介绍:
第一种是继承ClassLoader方法主要是用FileInputStream读取class,然后用defineClass方法返回class。注意在defineClass()方法的第一个参数必须设置成null。不然会抛出异常
package com.fnk.classloader; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; public class FileClassLoader extends ClassLoader { private String directory = "C:/"; // Default directory. private String type = ".class"; public FileClassLoader(String directory) { this.directory = directory; } public Class<?> findClass(String name) throws ClassNotFoundException { byte[] data; data = loadClassData(getFileName(name)); return defineClass(name, data, 0, data.length); } private String getFileName(String className){ int index = className.lastIndexOf("."); if(index != -1){ return className.substring(index + 1); }else{ return className; } } private byte[] loadClassData(String name) throws ClassNotFoundException { FileInputStream fis = null; ByteArrayOutputStream baos = null; try { fis = new FileInputStream(directory + name + type); baos = new ByteArrayOutputStream(); int len = 0; while ((len = fis.read()) != -1) { baos.write(len); } byte[] data = baos.toByteArray(); return data; } catch (Exception e) { e.printStackTrace(); throw new ClassNotFoundException(); } finally { if (fis != null) try { fis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (baos != null) try { baos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void main(String[] args) { FileClassLoader classLoader1 = new FileClassLoader( "./"); try { Class c1 = classLoader1.loadClass("com.fnk.classloader.TestClass"); Testf tc1 = (Testf)c1.newInstance(); tc1.test(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
第二种是 URLClassLoader 加载jar文件,然后调用loaderclass查找类。
package com.fnk.classloader; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; public class MyURLClassLoader { public static Class loaderClass(String file, String className) { URL url; Class myClass = null; try { url = new URL("file:" + file); URLClassLoader myClassLoader = new URLClassLoader( new URL[] { url }, Thread.currentThread() .getContextClassLoader()); myClass = myClassLoader.loadClass(className); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return myClass; } public static void main(String[] args) { try { Testf testf = (Testf)loaderClass("./TestClass.jar", "com.fnk.classloader.TestClass").newInstance(); testf.test(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
附件中是自定义的classloader
- ClassLoader.rar (10.2 KB)
- 下载次数: 12
发表评论
-
ReentrantLock
2011-09-27 22:45 1782昨天看了reentrantLock的源码码,分析一下 ... -
ClassLoader的 一些测试
2011-09-09 12:48 1200昨天写了ClassLoader原理的东西,今天对ClassLa ... -
Unsafe 源码分析
2011-08-19 21:56 2508这几天在分析ThreadPoolExecutor的时候看到了U ... -
TreeMap 源码分析
2011-08-18 15:42 1886TreeMap是一种红黑树。红黑树的介绍可以查看http:// ... -
Vector 源码分析
2011-08-18 12:04 1277Vector类继承了类AbstractList实现了接口imp ... -
LinkedHashSet 源码分析
2011-08-18 11:43 1142LinkedHashSet 通过继承hashSet();然后调 ... -
LinkedHashMap 源码分析
2011-08-18 11:34 2132LinkedHashMap 继承了HashMap<K,V ... -
Hashtable 源码分析
2011-08-18 10:41 2566hashtable实现了Map接口. 存储结构:类似于hash ... -
HashSet源码分析
2011-08-18 08:36 998存储结构: 通过hashmap来存储的 privat ... -
HashMap的源码分析
2011-08-18 08:17 1299存储结构:用数组来存桶的第一个节点。每个桶都是一个链表。里面存 ... -
HashMap的遍历源码
2011-08-14 16:49 1207遍历可以分为上面两种方法,hm.entrySet().iter ...
相关推荐
### Java ClassLoader原理详解 #### 摘要 本文探讨了Java虚拟机(JVM)中的一个重要特性:动态类加载(Dynamic Class Loading)。这一机制为Java平台提供了强大的能力,允许在运行时安装软件组件,例如从网络下载...
### WebSphere ClassLoader原理 #### 一、概述 在探讨WebSphere Application Server v6中的ClassLoaders之前,我们首先简要回顾一下ClassLoaders的基本概念及其在Java虚拟机(JVM)中的作用。 **ClassLoaders**是...
热更新通常依赖于类加载器(Classloader)的工作原理来实现,本篇文章将深入探讨如何利用Android的类加载器实现热更新的机制。 首先,我们需要理解什么是类加载器。在Java和Android中,类加载器是负责查找、加载和...
前面已经写过一篇关于java classloader的拙文java classloader原理初探。 时隔几年,再看一遍,觉得有些地方显得太过苍白,于是再来一篇: 完成一个Java类之后,经过javac编译,会生成一个class文件,这个...
本文将深入探讨ClassLoader的工作原理和类加载机制,帮助开发者理解这个至关重要的概念。 1. 类加载机制概述 Java的类加载机制遵循“双亲委派模型”(Delegation Model)。当一个类被加载时,它首先会尝试由当前...
学习ClassLoader的工作原理以及如何创建自己的ClassLoader是必要的。 首先,让我们深入了解ClassLoader的基本概念。在传统编程语言中,如C或C++,程序通常是一个单一的可执行文件,而Java则不同,它的编译结果是以...
一、Classloader的工作原理 Java的类加载机制遵循双亲委派模型,即当一个类加载器需要加载类时,它首先委托父类加载器尝试加载,只有当父类加载器无法加载时,才会尝试自己加载。这种设计避免了类的重复加载,并...
理解ClassLoader的工作原理以及如何定制它,对于深入学习Java的运行机制和进行高级应用开发具有重要意义。本篇文章将深入探讨Java ClassLoader的内部工作,并通过一个具体的实例来展示如何定制自己的ClassLoader。 ...
深入理解ClassLoader的工作原理对于优化应用性能、解决类加载问题以及实现自定义加载策略至关重要。 首先,JVM启动时,会构建一个类加载器的层次结构,主要包括三个基本类加载器: 1. Bootstrap ClassLoader:引导...
【图解版】深入分析ClassLoader类加载工作机制,从原理到JVM的装载过程,详情分析了ClassLoader加载类以及自定义类加载器的过程,不可用于商业用途,如有版权问题,请联系删除!
通过对`ClassLoader`的基本概念、工作原理、双亲委托机制以及不同类型的类加载器的了解,我们可以更好地理解Java类加载的过程及其背后的设计哲学。这对于深入理解Java虚拟机的内部机制以及开发高质量的应用程序都至...
本示例"ClassLoader小例子"将深入探讨这个概念,并通过一个具体的程序来演示其工作原理。下面我们将详细讨论ClassLoader的基本概念、工作流程以及如何自定义ClassLoader。 1. **ClassLoader的基本概念** - 类加载...
理解ClassLoader的工作原理对于优化Java应用程序性能以及解决类冲突等问题具有重要意义。 一、ClassLoader的基本概念 Java程序由多个类组成,每个类对应一个.class文件。当程序运行时,ClassLoader根据需要动态...
本文将深入浅出地探讨JVM ClassLoader的工作原理和相关知识点。 首先,ClassLoader可以分为三种基本类型:Bootstrap ClassLoader、Extension ClassLoader和Application ClassLoader。Bootstrap ClassLoader是JVM...
理解ClassLoader的工作原理对于优化应用性能、处理类加载问题以及实现自定义加载器至关重要。 首先,我们来了解一下ClassLoader的基本层次结构。在Java中,ClassLoader分为三个主要层次:Bootstrap ClassLoader、...
JBoss 5是一款知名的Java应用服务器,其在类加载(Class Loading)方面有着独特的处理方式...通过理解和掌握JBoss 5的类加载原理,开发者可以更有效地管理和优化应用程序的运行时环境,提高软件的可扩展性和可维护性。