2012-10-19 13 views
8

Attualmente sto creando un sistema di plugin (Il mio primo tentativo), guardare il codice di altri popoli che sto cercando di mettere insieme il mio programma di caricamento classe e ottenere i plugin caricati da una directory (Questi saranno di classe file)Java - dinamicamente classi di carico

il mio problema è che ogni volta che tento di caricare la classe con il mio programma di caricamento classe, qualsiasi importazione di plugin che fanno riferimento il programma non si trovano dal classloader. (es .: MyClass estende Plugin, com.mgmc.plugins noclassdeffound) Spazio dei nomi differente?

Alcuni codice di esempio: programma di caricamento classi:

/* 


* To change this template, choose Tools | Templates 
* and open the template in the editor. 
*/ 
package com.mcgm.game.provider; 

import com.mcgm.utils.Misc; 
import com.mcgm.utils.Paths; 
import java.awt.AWTPermission; 
import java.io.*; 
import java.net.MalformedURLException; 
import java.net.SocketPermission; 
import java.net.URL; 
import java.security.CodeSigner; 
import java.security.CodeSource; 
import java.security.Permissions; 
import java.security.ProtectionDomain; 
import java.util.PropertyPermission; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

/** 
* 
* @author Tom 
*/ 
public class GameClassLoader extends ClassLoader { 
private final ProtectionDomain domain; 
private final URL base; 

public GameClassLoader(final URL url) { 
    base = url; 
    final CodeSource codeSource = new CodeSource(base, (CodeSigner[]) null); 
    domain = new ProtectionDomain(codeSource, getPermissions()); 
} 

public void loadGames() { 
    for (File f : Paths.compiledFolder.listFiles()) { 
     try { 
      Class c = loadClass(f.getPath()); 
      Misc.outPrint(c.getName()); 
     } catch (ClassNotFoundException ex) { 
      Logger.getLogger(GameClassLoader.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 
} 

private Permissions getPermissions() { 
    final Permissions ps = new Permissions(); 
    ps.add(new AWTPermission("accessEventQueue")); 
    ps.add(new PropertyPermission("user.home", "read")); 
    ps.add(new PropertyPermission("java.vendor", "read")); 
    ps.add(new PropertyPermission("java.version", "read")); 
    ps.add(new PropertyPermission("os.name", "read")); 
    ps.add(new PropertyPermission("os.arch", "read")); 
    ps.add(new PropertyPermission("os.version", "read")); 
    ps.add(new SocketPermission("*", "resolve")); 
    ps.add(new FilePermission(Paths.compiledFolder.getPath(), "read,write,delete")); 
    ps.setReadOnly(); 
    return ps; 
} 

@Override 
@SuppressWarnings("rawtypes") 
public Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException { 
    Class clazz = findLoadedClass(name); 

    if (clazz == null) { 
     try { 
      byte[] bytes = loadClassData(name); 
      clazz = defineClass(name, bytes, 0, bytes.length, domain); 
      if (resolve) { 
       resolveClass(clazz); 
      } 
     } catch (final Exception e) { 
      clazz = super.loadClass(name, resolve); 
     } 
    } 

    return clazz; 
} 

public byte[] loadClassData(final String name) { 
    try { 
     final InputStream in = getResourceAsStream(name.replace('.', '/') + ".class"); 
     final byte[] buffer = new byte[4096]; 
     final ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     int n; 
     while ((n = in.read(buffer, 0, 4096)) != -1) { 
      out.write(buffer, 0, n); 
     } 
     return out.toByteArray(); 
    } catch (IOException ex) { 
     Logger.getLogger(GameClassLoader.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    return null; 

} 

@Override 
public URL getResource(final String name) { 
    try { 
     return new URL(base, name); 
    } catch (final MalformedURLException e) { 
     return null; 
    } 
} 

@Override 
public InputStream getResourceAsStream(final String name) { 
    try { 
     return new URL(base, name).openStream(); 
    } catch (final IOException e) { 
     return null; 
    } 
} 
} 

Il plugin che sto caricando: (L'annotazione non si trova neanche)

import com.mcgm.GameInfo; 
import com.mcgm.game.Minigame; 
    @GameInfo(name = "RandomGame", 
description = "A really long and boring game.", 
authors = {"Tom", "Is", "The", "Greatest"}, 
version = 0.1, 
maxPlayers = 100, 
teamBased = false, 
teamAmount = -1, 
PvP = false) 
public class game extends Minigame { 
} 

Come chiamo la classe per essere caricata :

Immagino che questo sia banale per quelli che sanno quello che stanno facendo!

+2

tu non sia un uomo onere. Le persone su SO stanno facendo domande o rispondendo a loro. Questo è figo. –

+0

Sono sorpreso: non hai pacchetti? Prevedo classLoader.loadClass ("a.b.c.d.game", true); – Aubin

+0

Sto cercando di non aggiungere pacchetti, solo a causa del modo in cui voglio che le persone siano in grado di aggiungere i propri minigiochi - So che va contro le convenzioni, ma in questo modo sono in grado di avere tutti i minigiochi in una singola cartella (O Jar) Alla fine eseguirà la scansione della cartella per tutti i file, controlla i file .class e .jar e li carica (Nessun pacchetto significa nessuna sottodirectory di scansione) –

risposta

4

FINALMENTE! Dopo un giorno e mezzo di ricerche, Vulcan mi ha segnalato nella giusta direzione: ho cambiato il GameClassLoader a:

public GameClassLoader(final URL url, ClassLoader parent) { 
    super(parent); 

e, infine, ha aggiunto l'URL di base per la getResourceAsStream()

final InputStream in = getResourceAsStream(base.getFile() + "/" + name.replace('.', '/') + ".class"); 

Grazie tanto per il tuo aiuto ragazzi!

+3

Felice di aver aiutato! Non dimenticare di contrassegnare la tua risposta come accettata per il futuro riferimento degli altri. – Vulcan

0

tenta di aggiungere barra che conduce in percorso risorsa: final InputStream in = getResourceAsStream("/" + name.replace('.', '/') + ".class");

Questa è la cosa che devo provare ogni volta che chiamo getResourceAsStream(). Ho appena provato di nuovo questo per te. Il percorso qui è relativo al pacchetto di classe che viene utilizzato per chiamare getResourceAsStream(), quindi è necessaria la barra iniziale per dire "inizia da root".

+0

Sfortunatamente questo non impedisce affatto il caricamento, il problema non sta caricando la classe; sta caricando le dipendenze della classe: java.lang.NoClassDefFoundError: com/mcgm/game/Minigame La classe è stata trovata assolutamente soddisfacente. –