2009-06-29 6 views
0

Ich möchte (und ich weiß nicht, ob es möglich ist) etwas tun, wenn jarA in meinem Klassenpfad ist und etwas anderes tut, wenn jarB in meinem Klassenpfad ist. Ich werde diese Gläser nicht in den Netbeans-Projektbibliotheksreferenzen angeben, weil ich nicht weiß, welches der Gläser verwendet wird.Java Reflektions- und Manifest-Datei in jar

Jetzt einschließlich der Glas in meinem Netbeans-Projekt Bibliothek Referenzen funktioniert, wenn ich versuche, die Jar-Klassen durch Reflexion zu verwenden. Aber wenn ich die netbeans-Projektbibliotheksreferenz entferne, aber das Glas zu meinem Klassenpfad hinzufüge, funktioniert die Reflexion nicht.

Meine Frage ist wirklich 1) kann dies getan werden? 2) Ich denke darüber richtig 3) Wie kommt es, wenn ich -cp oder -classpath angeben, um das Verzeichnis mit dem Jar aufzunehmen, funktioniert es nicht? 4) Wie kommt es, wenn ich das Verzeichnis in meinem manifest.mf in der JAR-Datei angeben, es funktioniert nicht?

Bitte lassen Sie es mich wissen. Das stört mich wirklich.

Danke, Julian

+1

Sie verwenden nicht -jar bist du? (Der Klassenpfad wird ignoriert.) –

+0

Ich verwende java -jar ... ok, das macht Sinn ... aber ich ging trotzdem in die Datei manifest.mf und änderte sie, um mein Verzeichnis zu verwenden, und es hat nicht funktioniert ... Immer noch versuchen herauszufinden, was vor sich geht, werden Sie auf dem Laufenden halten. – jbu

Antwort

1

auf Nummer 3 - sollten Sie den vollständig qualifizierten jar Namen in Ihrem Classpath enthalten, nicht nur das Verzeichnis.

+0

aber die Java-Hilfe-Optionen sagen Klassenpfad sucht einen Pfad von Verzeichnissen – jbu

+0

"-classpath A; getrennte Liste von Verzeichnissen, JAR-Archiven und ZIP-Archiven zur Suche nach Klassendateien". Ihr Kommentar ist nur teilweise korrekt - es gilt für Klassendateien, aber nicht JAR-Dateien. Alle Verweise auf Jar-Dateien auf dem Klassenpfad müssen vollständig qualifiziert sein – Dinuk

1

Ein Klassenpfad kann auf ein Verzeichnis verweisen, das .class-Dateien enthält, oder direkt auf eine .jar-Datei verweisen. Wenn es auf ein Verzeichnis verweist, das JAR-Dateien enthält, werden diese nicht einbezogen.


java -help sagt über -classpath: „Liste der Verzeichnisse, JAR-Archive, und ZIP-Archive für Klassendateien suchen.“ Das ist sehr klar, dass ein Verzeichnis auf dem Classpath für Klassendateien gesucht , nicht JAR-Archive.

1

Ich glaube schon!

ClassLoader.getSystemClassLoader()getURLs(); 

Dies wird Ihnen sagen, welche Jar-Dateien in Ihrem Klassenpfad sind. Dann mache X oder Y wie du willst.

+0

Hoppla, war wahrscheinlich nicht ganz klar. Es ist gut zu wissen, welche JAR-Dateien in meinem Klassenpfad sind, aber nachdem ich festgestellt habe, dass ich das JAR verwenden muss, das gefunden wurde. – jbu

+0

Ich brauche vielleicht ein wenig mehr Erklärung.Ist das Problem, dass Sie die gleiche Klasse haben, die in zwei verschiedenen JAR-Dateien in Ihrem Klassenpfad vorhanden sein kann? In diesem Fall könnte es schwierig sein, zwischen ihnen zu wählen. findClass (und damit loadClass) wird wahrscheinlich nur den ersten finden, den es findet. Wenn Sie zwei JAR-Dateien haben und die Quelle für Ihre Klasse auswählen möchten, suchen Sie lieber selbst mit den Dateifunktionen nach ihnen und erstellen Sie dann Ihren eigenen Klassenlader. Willst du ein Beispiel dafür? Ich habe irgendeinen Code irgendwo herumliegen. Sie können JAR-Dateien, die sich nicht in Ihrem Klassenpfad befinden, dynamisch laden. –

0

So mache ich es. Die innere Klasse kapselt die Singleton-Instanz des Loggers und seine Trace-Methode (heh - ich weiß - ein Singleton in einem Singleton). Die äußere Klasse benutzt sie nur, wenn die spezielle Klasse geladen werden kann, sonst gehen wir ohne sie weiter. Hoffentlich können Sie dies Ihren Bedürfnissen anpassen. Und alle Vorschläge zum besseren Code werden immer geschätzt! :-) HTH

import java.lang.reflect.Method; 
import java.text.SimpleDateFormat; 
import java.util.Date; 

/** 
* Provides centralized access to standardized output formatting. Output is sent to System.out and, 
* if the classpath allows it, to the Cisco CTIOS LogManager. (This is NOT a dependency, however.) 
* 
*/ 
public class LogWriter 
{ 
    protected static LogWriter me = null; 
    private SimpleDateFormat dateFormat = null; 
    private StringBuffer line = null; 
    CLogger ciscoLogger = null; 

    /* 
    * The following 2 methods constitute the thread-safe singleton pattern. 
    */ 
    private static class LogWriterHolder 
    { 
     public static LogWriter me = new LogWriter(); 
    } 
    /** 
    * Returns singleton instance of the class. Thread-safe. The only way to get one is to use this. 
    * 
    * @return an instance of LogWriter 
    */ 
    public static LogWriter sharedInstance() 
    { 
     return LogWriterHolder.me; 
    } 


    @SuppressWarnings("unchecked") 
    LogWriter() 
    { 
     dateFormat = new SimpleDateFormat("yyyyMMddHHmmss "); 
     line = new StringBuffer(); 
     try { 
      Class x = Class.forName("com.cisco.cti.ctios.util.LogManager"); 
      if(x != null) { 
       java.lang.reflect.Method m = x.getMethod("Instance", new Class[0]); 
       java.lang.reflect.Method n = x.getMethod("Trace", int.class, String.class); 
       if(m != null) { 
        Object y = m.invoke(x , new Object[0]); 
        if(n != null) { 
         ciscoLogger = new CLogger(); 
         ciscoLogger.target = y; 
         ciscoLogger.traceImpl = n ; 
        } 
       } 
      } 
     } catch(Throwable e) 
     { 
      System.err.println(e.getMessage()) ; 
      e.printStackTrace(); 
     } 
    } 

    /** 
    * Formats a line and sends to System.out. The collection and formatting of the text is 
    * thread safe. 
    * 
    * @param message  The human message you want to display in the log (required). 
    * @param hostAddress Host address of server (optional) 
    * @param hostPort  Port on hostAddresss (optional) - also used for className in object-specific logs. 
    */ 
    public void log(String message, String hostAddress, String hostPort) 
    { 
     if (message == null || message.length() < 3) return; 

     synchronized(this) 
     { 
      try { 
       line.delete(0, line.length()); 
       line.append(dateFormat.format(new Date())); 
       line.append(hostAddress); 
       line.append(":"); 
       line.append(hostPort); 
       line.append(" "); 
       while (line.length() < 28) 
        line.append(" "); 
       line.append(message); 

       this.write(line.toString()); 

      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    private void write(String line) 
    { 
     System.out.println(line) ; 
    } 

    /** 
    * Write a simple log message to output delegates (default is System.out). 
    * <p> 
    * Will prepend each line with date in yyyyMMddHHmmss format. there will be a big space 
    * after the date, in the spot where host and port are normally written, when {@link LogWriter#log(String, String, String) log(String,String,String)} 
    * is used. 
    * 
    * @param message What you want to record in the log. 
    */ 
    public void log(String message) 
    { 
     if(ciscoLogger != null) ciscoLogger.trace(0x01, message); 
     this.log(message, "", ""); 
    } 

    class CLogger 
    { 
     Object target; 
     Method traceImpl; 

     @SuppressWarnings("boxing") 
     public void trace(int x, String y) 
     { 
      try { 
       traceImpl.invoke(target, x, y) ; 
      } catch(Throwable e) { 
       // nothing to say about this 
      } 
     } 
    } 

}