posts - 28, comments - 37, trackbacks - 0, articles - 0
               最近這些天學(xué)習(xí)了classLoader的原理, 原因是因?yàn)榉?wù)器上的一個(gè)java進(jìn)程啟動(dòng)時(shí)加載兩個(gè)不同版本的jar包, 含有相同名字的類, 而且服務(wù)端的jar包排在前面, 我上傳的jar包排在后面, 于是每次都使用服務(wù)端的jar包, 我的jar包便無法生效, 因此希望修改classLader, 讓它按相反的順序加載jar包.
               網(wǎng)上查閱了classLoader的原理, 分析jvm默認(rèn)使用AppClassLoader加載classpath中的類, 因此目標(biāo)很明確, 替換它就行了, 找到一個(gè)參數(shù)
          java.system.class.loader, 只需要在啟動(dòng)java進(jìn)程的時(shí)候把它設(shè)置為自己的類就行.
               開始寫自己的classLoader, 參考URLClassLoader與網(wǎng)上的介紹, 寫了一個(gè)簡單的,上代碼:
            1 package org.taobao.yuling.testClassLoader;
            2 
            3 import java.io.*;
            4 import java.lang.reflect.*;
            5 import java.net.MalformedURLException;
            6 import java.net.URL;
            7 import java.net.URLClassLoader;
            8 import java.nio.ByteBuffer;
            9 import java.security.AccessControlContext;
           10 import java.security.AccessController;
           11 import java.security.CodeSigner;
           12 import java.security.CodeSource;
           13 import java.security.PermissionCollection;
           14 import java.security.PrivilegedAction;
           15 import java.security.SecureClassLoader;
           16 import java.util.Arrays;
           17 import java.util.HashMap;
           18 import java.util.Map;
           19 import java.util.jar.Attributes;
           20 import java.util.jar.Manifest;
           21 
           22 
           23 import sun.misc.JavaNetAccess;
           24 import sun.misc.Resource;
           25 import sun.misc.SharedSecrets;
           26 import sun.misc.URLClassPath;
           27 
           28 /**
           29  * The class loader used for loading from java.class.path.
           30  * runs in a restricted security context.
           31  */
           32 public class MyClassLoader extends URLClassLoader {
           33     public URLClassPath ucp;
           34       private Map<String, Class<?>> cache = new HashMap();
           35       private static final Method defineClassNoVerifyMethod;
           36       
           37       static String[] paths = System.getProperty("java.class.path").split(";");
           38       
           39       static URL[] urls = new URL[paths.length];
           40 
           41       static{
           42           System.out.println(Arrays.toString(paths));
           43           System.out.println(System.getProperty("java.class.path"));
           44           for(int i=0; i<urls.length; i++){
           45               try {
           46                   
           47                 urls[i] = new URL("file:"+paths[paths.length-1-i]);
           48             } catch (MalformedURLException e) {
           49                 e.printStackTrace();
           50             }
           51           }
           52           System.out.println(Arrays.toString(urls));
           53         SharedSecrets.setJavaNetAccess(new JavaNetAccess() {
           54           public URLClassPath getURLClassPath(URLClassLoader u) {
           55             return ((MyClassLoader)u).ucp;
           56           } } );
           57         Method m;
           58         try {
           59           m = SecureClassLoader.class.getDeclaredMethod(
           60             "defineClassNoVerify"new Class[] { String.class
           61             ByteBuffer.class, CodeSource.class });
           62           m.setAccessible(true);
           63         } catch (NoSuchMethodException nsme) {
           64           m = null;
           65         }
           66         defineClassNoVerifyMethod = m;
           67       }
           68       
           69       public MyClassLoader(URL[] urls) {
           70             super(MyClassLoader.urls);
           71             this.ucp = new URLClassPath(MyClassLoader.urls);
           72         }
           73       
           74       public MyClassLoader(ClassLoader parent) {
           75             super(MyClassLoader.urls, parent);
           76             this.ucp = new URLClassPath(MyClassLoader.urls);
           77         }
           78 
           79       public Class<?> loadClass(String name)
           80         throws ClassNotFoundException{
           81         Class c = null;
           82         
           83         if (name.contains("hadoop")) {
           84           c = (Class)this.cache.get(name);
           85           if (c == null) {
           86             c = findClass(name);
           87             this.cache.put(name, c);
           88           }
           89         } else {
           90           c = loadClass(name, false);
           91         }
           92         return c;
           93       }
           94 
           95       protected Class<?> findClass(String name)
           96         throws ClassNotFoundException
           97       {
           98         String path = name.replace('.''/').concat(".class");
           99         Resource res = this.ucp.getResource(path);
          100         if (res != null) {
          101           try {
          102             return defineClass(name, res, true);
          103           } catch (IOException e) {
          104             throw new ClassNotFoundException(name, e);
          105           }
          106         }
          107         throw new ClassNotFoundException(name);
          108       }
          109 
          110       private Class<?> defineClass(String name, Resource res, boolean verify) throws IOException
          111       {
          112         int i = name.lastIndexOf('.');
          113         URL url = res.getCodeSourceURL();
          114         if (i != -1) {
          115           String pkgname = name.substring(0, i);
          116 
          117           Package pkg = getPackage(pkgname);
          118           Manifest man = res.getManifest();
          119           if (pkg != null)
          120           {
          121             if (pkg.isSealed())
          122             {
          123               if (!pkg.isSealed(url)) {
          124                 throw new SecurityException(
          125                   "sealing violation: package " + pkgname + 
          126                   " is sealed");
          127               }
          128 
          129             }
          130             else if ((man != null&& (isSealed(pkgname, man))) {
          131               throw new SecurityException(
          132                 "sealing violation: can't seal package " + 
          133                 pkgname + ": already loaded");
          134             }
          135 
          136           }
          137           else if (man != null)
          138             definePackage(pkgname, man, url);
          139           else {
          140             definePackage(pkgname, nullnullnullnullnullnull
          141               null);
          142           }
          143 
          144         }
          145 
          146         ByteBuffer bb = res.getByteBuffer();
          147         byte[] bytes = bb == null ? res.getBytes() : null;
          148 
          149         CodeSigner[] signers = res.getCodeSigners();
          150         CodeSource cs = new CodeSource(url, signers);
          151 
          152         if (!verify)
          153         {
          154           Object[] args = { name, bb == null ? ByteBuffer.wrap(bytes) : bb, 
          155             cs };
          156           try {
          157             return (Class)defineClassNoVerifyMethod.invoke(this, args);
          158           }
          159           catch (IllegalAccessException localIllegalAccessException) {
          160           }
          161           catch (InvocationTargetException ite) {
          162             Throwable te = ite.getTargetException();
          163             if ((te instanceof LinkageError))
          164               throw ((LinkageError)te);
          165             if ((te instanceof RuntimeException)) {
          166               throw ((RuntimeException)te);
          167             }
          168             throw new RuntimeException("Error defining class " + name, 
          169               te);
          170           }
          171 
          172         }
          173         return defineClass(name, bytes, 0, bytes.length, cs);
          174       }
          175 
          176       private boolean isSealed(String name, Manifest man) {
          177         String path = name.replace('.''/').concat("/");
          178         Attributes attr = man.getAttributes(path);
          179         String sealed = null;
          180         if (attr != null) {
          181           sealed = attr.getValue(Attributes.Name.SEALED);
          182         }
          183         if ((sealed == null&& 
          184           ((attr = man.getMainAttributes()) != null)) {
          185           sealed = attr.getValue(Attributes.Name.SEALED);
          186         }
          187 
          188         return "true".equalsIgnoreCase(sealed);
          189       }
          190 }
          191 
          注: isSealed(), defineClass(), findClass(), 都是直接從URLClassLoader復(fù)制過來.
          代碼較粗糙, 不過意思很簡單, 就是通過把java.class.path的jar包反順序, 然后定義了自己的
          Class<?> loadClass(String name) 方法, 在加載我需要的類時(shí)在已被反序的的jar包中查找, 這樣就能首先加載我修改的類了.
          運(yùn)行方法:
          java -Djava.system.class.loader=org.taobao.yuling.testClassLoader.MyClassLoader -classpath ...  MyTestClass

          Feedback

          # re: 實(shí)現(xiàn)自定義的classLoader加載classpath中的class[未登錄]  回復(fù)  更多評(píng)論   

          2015-01-07 14:03 by 阿帕奇
          挺不錯(cuò)的。、

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 沧州市| 读书| 湖州市| 广平县| 庆城县| 金塔县| 舞钢市| 堆龙德庆县| 枝江市| 东丰县| 安阳市| 仙桃市| 武鸣县| 锦屏县| 沾益县| 广宁县| 信阳市| 灌阳县| 金寨县| 天全县| 临沂市| 东至县| 长阳| 尉犁县| 漯河市| 黎川县| 夏河县| 沛县| 聂荣县| 乐安县| 区。| 浮梁县| 江油市| 泰来县| 招远市| 冷水江市| 革吉县| 宁蒗| 乐平市| 来凤县| 自贡市|