Java动态加载类
Posted
技术标签:
【中文标题】Java动态加载类【英文标题】:Java Dynamically Loading a class 【发布时间】:2011-04-04 14:10:43 【问题描述】:我正在尝试将类动态加载到组件中。我正在使用文件选择器来选择将要加载的 .JAR 文件,然后使用选项窗格来获取类的名称。
我在网上搜索了如何将 java 文件转换为 URL 以便在 URLClassLoader 中加载它,我想出了:
File myFile = filechooser.getSelectedFile();
String className = JOptionPane.showInputDialog(
this, "Class Name:", "Class Name", JOptionPane.QUESTION_MESSAGE);
URL myUrl= null;
try
myUrl = myFile.toURL();
catch (MalformedURLException e)
URLClassLoader loader = new URLClassLoader(myUrl);
loader.loadClass(className);
我现在在将 URL 加载到 URLClassLoader 时遇到“找不到符号”错误
【问题讨论】:
是一个词吗?谷歌唯一建议的是“被控制”:-) urbandictionary.com/define.php?term=trolled @seanizer: “trawled”——作为搜索的一部分进行筛选。 @trashgod 听起来好多了... 相关:Adding files to java classpath at runtime 【参考方案1】:URLClassLoadertakes an array of URLs的构造函数,不是单个URL。
【讨论】:
【参考方案2】:看看这个相关的问题:How should I load Jars dynamically at runtime?
【讨论】:
【参考方案3】:ClassPathHacker.java
在this forum thread 中找到,是一个动态加载类的选项。
import java.lang.reflect.*;
import java.io.*;
import java.net.*;
public class ClassPathHacker
private static final Class[] parameters = new Class[]URL.class;
public static void addFile(String s) throws IOException
File f = new File(s);
addFile(f);
//end method
public static void addFile(File f) throws IOException
addURL(f.toURL());
//end method
public static void addURL(URL u) throws IOException
URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
Class sysclass = URLClassLoader.class;
try
Method method = sysclass.getDeclaredMethod("addURL",parameters);
method.setAccessible(true);
method.invoke(sysloader,new Object[] u );
catch (Throwable t)
t.printStackTrace();
throw new IOException("Error, could not add URL to system classloader");
//end try catch
//end method
//end class
【讨论】:
【参考方案4】:我喜欢the answer by Zellus 中提到的 ClassPathHacker 类,但它充满了不推荐使用的调用和不良做法,所以这里有一个重写版本,它还缓存了 Classloader 和 addUrl 方法:
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.io.IOException;
import java.io.File;
public class ClassPathHacker
private static final Class<URLClassLoader> URLCLASSLOADER =
URLClassLoader.class;
private static final Class<?>[] PARAMS = new Class[] URL.class ;
public static void addFile(final String s) throws IOException
addFile(new File(s));
public static void addFile(final File f) throws IOException
addURL(f.toURI().toURL());
public static void addURL(final URL u) throws IOException
final URLClassLoader urlClassLoader = getUrlClassLoader();
try
final Method method = getAddUrlMethod();
method.setAccessible(true);
method.invoke(urlClassLoader, new Object[] u );
catch(final Exception e)
throw new IOException(
"Error, could not add URL to system classloader");
private static Method getAddUrlMethod()
throws NoSuchMethodException
if(addUrlMethod == null)
addUrlMethod =
URLCLASSLOADER.getDeclaredMethod("addURL", PARAMS);
return addUrlMethod;
private static URLClassLoader urlClassLoader;
private static Method addUrlMethod;
private static URLClassLoader getUrlClassLoader()
if(urlClassLoader == null)
final ClassLoader sysloader =
ClassLoader.getSystemClassLoader();
if(sysloader instanceof URLClassLoader)
urlClassLoader = (URLClassLoader) sysloader;
else
throw new IllegalStateException(
"Not an UrlClassLoader: "
+ sysloader);
return urlClassLoader;
【讨论】:
【参考方案5】:我在 scala 中重写了这个,以防万一有人需要,因为它不是 100% 微不足道的 :)
/*
* Class which allows URLS to be "dynamically" added to system class loader
*/
object class_path_updater
val URLCLASSLOADER = classOf[URLClassLoader]
var urlClassLoader = getUrlClassLoader
var addUrlMethod = getAddUrlMethod
/*
* addFile - have to use reflection to retrieve and call class loader addURL method as it is protected
*/
def addFile(s: String) =
val urlClassLoader = getUrlClassLoader
try
val method = getAddUrlMethod
method.setAccessible(true)
val v = (new File(s)).toURI.toURL
invoke(urlClassLoader, method, Array[AnyRef](v))
def invoke(proxy: AnyRef, m: Method, args: Array[AnyRef]) = m.invoke(proxy, args: _*)
private def getAddUrlMethod: Method =
if (addUrlMethod == null) addUrlMethod = URLCLASSLOADER.getDeclaredMethod("addURL", classOf[URL])
addUrlMethod
private def getUrlClassLoader: URLClassLoader =
if (urlClassLoader == null)
val sysLoader = ClassLoader.getSystemClassLoader
sysLoader match
case x: URLClassLoader => urlClassLoader = sysLoader.asInstanceOf[URLClassLoader]
case _ => throw new IllegalStateException("Not a UrlClassLoader: " + sysLoader)
urlClassLoader
【讨论】:
以上是关于Java动态加载类的主要内容,如果未能解决你的问题,请参考以下文章