东莞陈村网站制作,介绍西安网页设计,洛可可设计公司招聘,济南网站制作搜到通过ClassLoader调用外部jar包 我们大家都知道#xff0c;每个运行中的线程都有一个成员contextClassLoader#xff0c;用来在运行时动态地载入其它类。 系统默认的contextClassLoader是systemClassLoader#xff0c;所以一般而言java程序在执行时可以使用JVM自带的类、$JAV… 通过ClassLoader调用外部jar包 我们大家都知道每个运行中的线程都有一个成员contextClassLoader用来在运行时动态地载入其它类。 系统默认的contextClassLoader是systemClassLoader所以一般而言java程序在执行时可以使用JVM自带的类、$JAVA_HOME/jre/lib/ext/中的类和$CLASSPATH/中的类对于非默认的jar一般只能手动在配置环境添加。 但事实上我们可以通过Thread.currentThread().setContextClassLoader()更改当前线程的contextClassLoader行为实现在程序内加载外部jar。 PS:ClassLoader的工作原理是1) 线程需要用到某个类时contextClassLoader将被请求来载入该类2) contextClassLoader请求它的父ClassLoader来完成该载入请求3) 如果父ClassLoader无法载入类则contextClassLoader试图自己来载入 package org.loon.framework.jar;/** *//** * pTitle: LoonFramework/p * pDescription:JarLoader用于jar包的外部操作/p * pCopyright: Copyright (c) 2007/p * pCompany: LoonFramework/p * author chenpeng * emailceponlineyahoo.com.cn * version 0.1 */import java.io.BufferedInputStream;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.lang.reflect.Method;import java.net.MalformedURLException;import java.net.URL;import java.util.ArrayList;import java.util.HashMap;import java.util.Hashtable;import java.util.jar.JarEntry;import java.util.jar.JarInputStream;import java.util.jar.Manifest;public class JarLoader extends ClassLoader ...{ //资源缓存 public static Hashtable resources new Hashtable(); public static JarLoader loader new JarLoader(); public static Class load(byte[] resource) throws Exception ...{ // 主函数所在类全称 String mainClassName ; //class资源及实体缓存 ArrayList classNames new ArrayList(); ArrayList classBuffers new ArrayList(); // 存储依赖类 HashMap depends new HashMap(); // 将byte[]转为JarInputStream JarInputStream jar new JarInputStream(new ByteArrayInputStream( resource)); Manifest manifest jar.getManifest(); // 当Main-Class被声明时,获得主函数所在类全称 if (manifest ! null) ...{ mainClassName manifest.getMainAttributes().getValue(Main-Class); } // 依次获得对应JAR文件中封装的各个被压缩文件的JarEntry JarEntry entry; while ((entry jar.getNextJarEntry()) ! null) ...{ // 当找到的entry为class时 if (entry.getName().toLowerCase().endsWith(.class)) ...{ // 将类路径转变为类全称 String name entry.getName().substring(0, entry.getName().length() - .class.length()).replace( /, .); // 加载该类 byte[] data getResourceData(jar); // 缓存类名及数据 classNames.add(name); classBuffers.add(data); } else ...{ // 非class结尾但开头字符为/时 if (entry.getName().charAt(0) /) ...{ resources.put(entry.getName(), getResourceData(jar)); // 否则追加/后缓存 } else ...{ resources.put(/ entry.getName(), getResourceData(jar)); } } } //当获得的main-class名不为空时 while (classNames.size() 0) ...{ //获得类路径全长 int n classNames.size(); for (int i classNames.size() - 1; i 0; i--) ...{ try ...{ //查询指定类 loader.defineClass((String) classNames.get(i), (byte[]) classBuffers.get(i), 0, ((byte[]) classBuffers.get(i)).length); //获得类名 String pkName (String) classNames.get(i); if (pkName.lastIndexOf(.) 0) ...{ pkName pkName .substring(0, pkName.lastIndexOf(.)); if (loader.getPackage(pkName) null) ...{ loader.definePackage(pkName, null, null, null, null, null, null, null); } } //查询后删除缓冲 classNames.remove(i); classBuffers.remove(i); } catch (NoClassDefFoundError e) ...{ depends.put((String) classNames.get(i), e.getMessage() .replaceAll(/, .)); } catch (UnsupportedClassVersionError e) ...{ //jre版本错误提示 throw new UnsupportedClassVersionError(classNames.get(i) , System.getProperty(java.vm.name) System.getProperty(java.vm.version) )); } } if (n classNames.size()) ...{ for (int i 0; i classNames.size(); i) ...{ System.err.println(NoClassDefFoundError: classNames.get(i)); String className (String) classNames.get(i); while (depends.containsKey(className)) ...{ className (String) depends.get(className); } } break; } } try ...{ //加载 Thread.currentThread().setContextClassLoader(loader); // 获得指定类,查找其他类方式相仿 return Class.forName(mainClassName, true, loader); } catch (ClassNotFoundException e) ...{ String className mainClassName; while (depends.containsKey(className)) ...{ className (String) depends.get(className); } throw new ClassNotFoundException(className); } } /** *//** * 获得指定路径文件的byte[]形式 * param name * return */ final static public byte[] getDataSource(String name) ...{ FileInputStream fileInput; try ...{ fileInput new FileInputStream(new File(name)); } catch (FileNotFoundException e) ...{ fileInput null; } BufferedInputStream bufferedInput new BufferedInputStream(fileInput); return getDataSource(bufferedInput); } /** *//** * 获得指定InputStream的byte[]形式 * param name * return */ final static public byte[] getDataSource(InputStream is) ...{ if (is null) ...{ return null; } ByteArrayOutputStream byteArrayOutputStream new ByteArrayOutputStream(); byte[] arrayByte null; try ...{ byte[] bytes new byte[8192]; bytes new byte[is.available()]; int read; while ((read is.read(bytes)) 0) ...{ byteArrayOutputStream.write(bytes, 0, read); } arrayByte byteArrayOutputStream.toByteArray(); } catch (IOException e) ...{ return null; } finally ...{ try ...{ if (byteArrayOutputStream ! null) ...{ byteArrayOutputStream.close(); byteArrayOutputStream null; } if (is ! null) ...{ is.close(); is null; } } catch (IOException e) ...{ } } return arrayByte; } /** *//** * 获得指定JarInputStream的byte[]形式 * param jar * return * throws IOException */ final static private byte[] getResourceData(JarInputStream jar) throws IOException ...{ ByteArrayOutputStream data new ByteArrayOutputStream(); byte[] buffer new byte[8192]; int size; while (jar.available() 0) ...{ size jar.read(buffer); if (size 0) ...{ data.write(buffer, 0, size); } } return data.toByteArray(); } /** *//** * 重载的getResource,检查是否重复包含 */ public URL getResource(String name) ...{ if (resources.containsKey(/ name)) ...{ try ...{ return new URL(file:/// name); } catch (MalformedURLException e) ...{ e.printStackTrace(); } } return super.getResource(name); } /** *//** * 执行指定class类 * param clz * param methodName * param args */ public static void callVoidMethod(Class clz, String methodName, String[] args) ...{ Class[] arg new Class[1]; arg[0] args.getClass(); try ...{ Method method clz.getMethod(methodName, arg); Object[] inArg new Object[1]; inArg[0] args; method.invoke(clz, inArg); } catch (Exception e) ...{ System.err.println(e.getMessage()); } } /** *//** * 重载的getResourceAsStream,检查是否重复包含 */ public InputStream getResourceAsStream(String name) ...{ if (name.charAt(0) /) ...{ name name.substring(1); } if (resources.containsKey(/ name)) ...{ return new ByteArrayInputStream((byte[]) resources.get(/ name)); } return super.getResourceAsStream(name); }} 运行示例 package org.loon.framework.jar;/** *//** * p * Title: LoonFramework * /p * p * Description:从外部启动jar包 * /p * p * Copyright: Copyright (c) 2007 * /p * p * Company: LoonFramework * /p * * author chenpeng * emailceponlineyahoo.com.cn * version 0.1 */public class JarTest ...{ public static void main(String[] args) ...{ //将jar包转为byte[] byte[] resource JarLoader.getDataSource(D:/fps_test.jar); try ...{ //通过byte[]获得主函数所在类 Class clz JarLoader.load(resource); //调用main函数 JarLoader.callVoidMethod(clz, main, new String[] ...{}); } catch (Exception e) ...{ e.getStackTrace(); } }} 这时即使指定jar包没有被我们添加到lib中程序依旧被顺利启动了。但是有个缺点在没有优化的前提下这种直接加载外部包的速度在jvm会有很大损耗。我们可以看到fps值降低到正常值的50%左右此fps实例见我CSDN以前的文章所以并不适合直接运用在需要复杂运算的jar中类调用上当然有兴趣的话可以在代码中优化我自己在项目中写的另一个例子速度明显比这个快。但是对于运算量小的外部jar调用还是很方便的。 posted on 2007-11-12 15:38 cping 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/cping1982/archive/2007/11/12/2258094.html