2017-10-21 2 views
0

私のアプリケーション用のプラグインシステムを実装しようとしています。そのコードは、カスタム機能を定義するためにPluginクラスを拡張しています。実行時に.classをjarから作業ディレクトリにロードするには?

アプリケーションの.jarファイルと同じディレクトリに、jarファイル内からクラスをロードするためにこのコードは、正常に動作します:

の正しい応答をもたらす
if(pluginName.endsWith(".jar")) 
{ 
    JarFile jarFile = new JarFile(pluginName); 
    Enumeration jarComponents = jarFile.entries(); 

    while (jarComponents.hasMoreElements()) 
    { 
     JarEntry entry = (JarEntry) jarComponents.nextElement(); 
     if(entry.getName().endsWith(".class")) 
     { 
      className = entry.getName(); 
     } 
    } 

    File file = new File(System.getProperty("user.dir")+"/"+pluginName); 
    URLClassLoader loader = new URLClassLoader(new URL[]{file.toURI().toURL()}); 

    Class newClass = Class.forName(className.replace(".class", ""), true, loader); 
    newPlugin = (Plugin) newClass.newInstance(); 
} 

benpalmer$ java -jar assignment.jar test_subproject.jar 
- INFO: Add new plugin: source.com 

問題は、プラグインシステムの目的のために.jarに実際にすべてがパックされているので、代わりに.classファイルを指定するオプションをユーザに提供することです。以下になり

else if(pluginName.endsWith(".class")) 
{ 
    File file = new File(System.getProperty("user.dir")+"/"+pluginName); 
    URLClassLoader loader = new URLClassLoader(new URL[]{file.toURI().toURL()}); 

    Class newClass = Class.forName(className.replace(".class", ""), true, loader); 
    newPlugin = (Plugin) newClass.newInstance(); 
} 
... exception handling 

benpalmer$ java -jar assignment.jar TestPlugin.class 
SEVERE: Error: Plugin class not found. Class name: 
java.lang.ClassNotFoundException: 
    at java.lang.Class.forName0(Native Method) 
    at java.lang.Class.forName(Class.java:348) 
    at newsfeed.model.Plugin.loadClassFromJarFile(Plugin.java:144) 
    at newsfeed.controller.NFWindowController.initPlugins(NFWindowController.java:81) 
    at newsfeed.controller.NewsFeed$1.run(NewsFeed.java:20) 
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311) 
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756) 
    at java.awt.EventQueue.access$500(EventQueue.java:97) 
    at java.awt.EventQueue$3.run(EventQueue.java:709) 
    at java.awt.EventQueue$3.run(EventQueue.java:703) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80) 
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:726) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93) 
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82) 

私は上記のコードとパス名/他のオプションの多くのバリエーションを試してみましたが、ClassNotFoundExceptionが毎回取得しました。もともとはJARファイルの読み込みに問題がありましたが、完全修飾パスを使用して固定されていたので、クラスを読み込めません。

アイデア? :)

+0

あなたは本当に使うべき[ServiceLoader](https://docs.oracle.com/javase/9​​/docs/api/java/util/ServiceLoader.html)このため。 – VGR

答えて

0

私の質問をもう一度見て、自分の問題に見つけた解決策を投稿するのを忘れてしまったことに気付きました。私はこれが私の状況のた​​めに見つけた唯一の実例である、大学の課題の問題として、これが将来誰かを助けることを願っています。私はそれがこの簡単だった信じることができません。

byte[] classData = Files.readAllBytes(Paths.get(fileName)); 
Class<?> cls = defineClass(null, classData, 0, classData.length); 
return (PluginClassName)cls.newInstance(); 
1

これはクラスのディレクトリで動作するURLClassLoaderの機能です(パックディレクトリとして.jarとすることがあります)。

constructor使用しているが、次のJavadocのデフォルトの委譲の親であるClassLoaderを使って、指定されたURLの新しいURLClassLoaderを構築し

を持っています。親クラスローダーで最初に検索した後、URLはクラスおよびリソースに指定された順序で検索されます。 '/'で終わるURLはディレクトリを指すものとみなされます。それ以外の場合、URLは必要に応じてダウンロードされて開かれるJARファイルを参照するものとみなされます。

あなたは絶対にあなたがSecureClassLoaderをサブクラス化し、defineClass方法で手動で新しいクラスを定義する検討すべき各個別のクラスのクラスローダを作成したい場合。

The basics of Java class loaders記事はあなたに役立つはずです。

+0

ここにあなたの助言をありがとう。その制約と時間制約を実装するのが難しいため、.classファイルを許可しないように決めました。 –

関連する問題