![](/img/trans.png)
[英]Java How to load classes out of a jar in the classpath with the System ClassLoader (no URLClassLoader)?
[英]understanding urlclassloader, how to access a loaded jar's classes
我試圖了解如何使用URLClassLoader訪問/提供一個jar文件。
首先,我用
package myA;
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 org.jgroups.JChannel;
public class loader {
JChannel channel;
String user_name=System.getProperty("user.name", "n/a");
private void start() throws Exception {
channel=new JChannel(); // use the default config, udp.xml
channel.connect("ChatCluster");
}
public void loadMe()throws ClassNotFoundException, MalformedURLException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
URL classUrl;
classUrl = new URL("file:///home/myJars/jgroups-3.4.2.Final.jar");
URL[] classUrls = { classUrl };
URLClassLoader ucl = new URLClassLoader(classUrls);
Class<?> c = ucl.loadClass("org.jgroups.JChannel");
for(Field f: c.getDeclaredFields()) {
System.out.println("Field name=" + f.getName());
}
Object instance = c.newInstance();
//Method theMethod = c.getMethod("main");
//theMethod.invoke(instance);
}
public static void main(String[] args) throws Exception {
new loader().loadMe();
new loader().start();
}
}
打印輸出顯示jgroups-3.4.2.Final.jar中已聲明的字段,但是隨后拋出classnotfound錯誤。
java -cp myA.jar myA.loader
Field name=DEFAULT_PROTOCOL_STACK
Field name=local_addr
Field name=address_generator
Field name=name
Field name=cluster_name
Field name=my_view
Field name=prot_stack
Field name=state_promise
Field name=state_transfer_supported
Field name=flush_supported
Field name=config
Field name=stats
Field name=sent_msgs
Field name=received_msgs
Field name=sent_bytes
Field name=received_bytes
Field name=probe_handler
Exception in thread "main" java.lang.NoClassDefFoundError: org/jgroups/JChannel
at myA.loader.start(loader.java:23)
at myA.loader.main(loader.java:45)
Caused by: java.lang.ClassNotFoundException: org.jgroups.JChannel
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
... 2 more
我不明白為什么打印輸出顯示已加載該類,但是卻找不到該類?
藝術
您的代碼可能有幾個問題。 首先,您在main中實例化加載程序2次,因此第二個實例與第一個實例無關,並且可能不知道第一個實例加載了JChannel
的類文件定義。
此外,您之前已將JChannel定義為loader
的成員,因此JRE在啟動時應為其定義類定義-否則它不應該知道該字段應該是什么。 我已將其替換為您通過URLClassLoader
加載的類,您應該在start()
實例化該類。
package myA;
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 org.jgroups.JChannel;
public class Loader
{
Class<?> clazz;
String user_name=System.getProperty("user.name", "n/a");
private void start() throws Exception
{
if (this.clazz == null)
throw new Exception("Channel class was not loaded properly");
Object channel = this.clazz.newInstance(); // use the default config, udp.xml
Method chatCluster = this.clazz.getDeclaredMethod("connect", new Class[] { String.class });
chatCluster.invoke(channel, "ChatCluster");
}
public void loadMe() throws Exception
{
URL classUrl;
classUrl = new URL("file:///home/myJars/jgroups-3.4.2.Final.jar");
URL[] classUrls = { classUrl };
URLClassLoader ucl = new URLClassLoader(classUrls);
Class<?> c = ucl.loadClass("org.jgroups.JChannel");
for(Field f: c.getDeclaredFields())
{
System.out.println("Field name=" + f.getName());
}
this.clazz = c;
Object instance = c.newInstance();
//Method theMethod = c.getMethod("main");
//theMethod.invoke(instance);
}
public static void main(String[] args) throws Exception
{
Loader loader = new Loader();
loader.loadMe();
loader.start();
}
}
您應該進一步在代碼中添加一些錯誤處理。
Exception in thread "main" java.lang.NoClassDefFoundError: org/jgroups/JChannel
at myA.loader.start(loader.java:23)
代碼在此行失敗:
channel=new JChannel(); // use the default config, udp.xml
加載程序的ClassLoader不可見JChannel類型。 如果您嘗試以下操作,這將很明顯:
loader.class
.getClassLoader()
.loadClass("org.jgroups.JChannel");
在運行時,您不應有對依賴項的任何編譯時引用,而這些依賴關系將不在類型的類路徑上。
使用新的子類ClassLoader進行加載不會將該類型添加到某些全局類池中。 加載程序具有子級與父級關系的層次結構。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.