Package name aus Class-File auslesen

Status
Nicht offen für weitere Antworten.
H

Harry

Gast
Hi
ich hab da mal nen kleines Problem
ich möchte aus einem Class-file (z.B "C.\Test.class")
den Packagenamen auslesen.

MFG

Harry
 
H

Harry

Gast
Das Problem ist ja, dass ich an die Class garnicht rankomme,
da ich für den URLClassLoader die Classe nur über den kompletten namen (package+Classname) Laden kann

MFG

Harry
 
S

stev.glasow

Gast
???:L Wieso hast du denn eine Klasse von der du nicht weißt in welchem Paket sie liegt?
 

Karl

Aktives Mitglied
Hallo,

wenn ich das richtig verstehe, hat er das Problem, dass da ein einsames verwaistes class-File liegt und er will
wissen, in welches Package das gehört.

Es sind dabei zwei Situationen zu unterscheiden:
A) Die Klasse "liegt nur falsch", könnte aber geladen werden, wenn sie richtig läge.
B) Die Klasse kann definitiv erst einmal nicht geladen werden (z.B. weil Abhängigkeiten nicht erfüllt sind oder die
VM nicht passt)

zu A):
Wie bereits richtig bemerkt, versagt der URLClassLoader, weil dieser nämlich merkt, dass die Klasse nicht
da ist, wo sie hingehört oder einen falschen Dateinamen hat. Mit einem Trick kann man sie dennoch laden.
Man baut dazu einen ClassLoader, der bei defineClass(name, ...) name=null übergibt. Die Namens- und Paket-Prüfung
wird so unterbunden. Sobald die Klasse geladen ist, lassen sich ihre Eigenschaften per Reflection bestimmen.
Hinweis: Es könnte Probleme mit dieser Lösung geben, wenn eine Klasse gleichen Namens bereits über den regulären ClassPath
geladen wurde.

zu B):
Das ist unangenehm. Dazu muss man den Bytecode untersuchen (siehe VM-Spec). Das ist ein wenig aufwändig ;-)

Gruß,
Karl
 

Sky

Top Contributor
Karl hat gesagt.:
zu B):
Das ist unangenehm. Dazu muss man den Bytecode untersuchen (siehe VM-Spec). Das ist ein wenig aufwändig ;-)

Das bringt mich auf eine Idee: Einfach mal das .class-File decompilieren und reingucken.
 

Karl

Aktives Mitglied
Hallo,

keine schlechte Idee, aber aus einem Java-Programm heraus einen Decompiler aufrufen und den Output parsen ist irgendwie auch nicht der Hit.

Wie ich gerade festgestellt habe, ist der Beginn des Bytecodes gar nicht so schwer lesbar. Das ist eigentlich eine große Tabelle mit Einträgen, die auf andere Verweisen können.

BTW: Wusstet Ihr, dass jede Java Klasse mit CAFEBABE (HEX) beginnt? Wer ist das, muss man die kennen? :D

Gruß,
Karl
 
H

Harry

Gast
Hi Karl
kannst du mir mal nen kleines beispiel geben für deinen lösungsansatz a. ???
kann mir das noch nicht richtig vorstellen wie ich das mit dem ClassLoader anstellen soll ohne den KlassenNamen.

THX

Harry

ps: jaja die Cafe ist schon ne süße ;)
 

Karl

Aktives Mitglied
Hallo Harry,

also ich habe mal beide Varianten probiert.

Variante 1 (Wild Loading ;-) ):


Code:
    /**
     * Diese Methode ermittelt den voll qualifizierten Klassennamen.
     * Dazu wird die Klasse kurz geladen.
     * @param sFileName Dateiname (Class File)
     * @return String mit voll qualifiziertem Klassennamen
     * @throws ClassFormatError falls Name nicht ermittelbar (nicht ladbar)
     * @throws FileNotFoundException
     * @throws IOException
     */
    public static String getNameFromClassFile(String sFileName) throws FileNotFoundException, IOException {
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        String sName = null;
        try {
            fis = new FileInputStream(sFileName);
            bis = new BufferedInputStream(fis);
            int size = 0;
            int iLastRead = 0;
            ByteArrayOutputStream bos = null;
            if (bis != null) {
                byte[] buffer = new byte[10000];
                try {
                    bos = new ByteArrayOutputStream(30000);
                    while (iLastRead > -1) {
                        iLastRead = bis.read(buffer, 0, 10000);
                        if (iLastRead > -1) {
                            size = size + iLastRead;
                            bos.write(buffer, 0, iLastRead);
                        }
                    }
                    buffer = bos.toByteArray();
                } finally {
                    if (bos != null) {
                        try {
                            bos.close();
                        } catch (Throwable t) {
                        }
                    }
                }
                class UglyLoader extends ClassLoader { //so baut man normaler weise keinen ClassLoader ;-)
                    public Class defineClassNow(byte[] b, int off, int len) throws ClassFormatError {
                        // Man beachte, dass durch das erste null verhindert wird, dass
                        // irgendwelche Prüfungen bzgl. Namen oder Package vorgenommen werden
                        return defineClass(null, b, off, len);
                    }
                }
                UglyLoader ul = new UglyLoader();
                Class cl = ul.defineClassNow(buffer, 0, buffer.length);
                sName = cl.getName();
            }
        }
        finally {
            try {
                fis.close();
            }
            catch (Throwable t) {}
        }
        if (sName == null) {
            throw new ClassFormatError("Name konnte nicht ermittelt werden.");
        }
        return sName;
    }

Variante 2 (Byte Code Analyse):


Code:
    /**
     * Diese Methode ermittelt den voll qualifizierten Klassennamen.
     * Dazu wird das Class File (Binary) untersucht.
     * @param sFileName Dateiname (Class File)
     * @return String mit voll qualifiziertem Klassennamen
     * @throws ClassFormatError falls Fehler im Format
     * @throws FileNotFoundException
     * @throws IOException
     */
    private static String getNameFromClassFile(String sFileName) throws FileNotFoundException, IOException {
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        DataInputStream dis = null;
        String sName = null;
        try {
            fis = new FileInputStream(sFileName);
            bis = new BufferedInputStream(fis);
            dis = new DataInputStream(bis);
            int magic = dis.readInt();
            if (!"cafebabe".equals(Integer.toHexString(magic))) {
                throw new ClassFormatError("Kein Java Class File.");
            }
            dis.readUnsignedShort(); //minor version
            dis.readUnsignedShort(); //major version
            int constant_pool_count = dis.readUnsignedShort() - 1;
            //Konstantenpool teilweise auslesen (lückenhaft, nur relevante)
            String[] constant_pool = new String[constant_pool_count];
            for (int i = 0; i < constant_pool_count; i++) {
                int tag = dis.readUnsignedByte();
                if (tag == 7) { //Klasseninformation
                    constant_pool[i] = "" + (dis.readUnsignedShort()-1); //Position des Namens merken
                }
                else if (tag == 1) { //das ist der Inhalt eines Strings (also auch der Klassenname)
                    int len = dis.readUnsignedShort();
                    byte[] bytes = new byte[len];
                    for (int k = 0; k < len; k++) {
                        bytes[k] = (byte)dis.readUnsignedByte();
                    }
                    constant_pool[i] = new String(bytes, "UTF-8");
                } //alles andere skippen
                else if (tag > 8 && tag < 13) {
                    dis.readUnsignedShort();
                    dis.readUnsignedShort();
                }
                else if (tag == 8) dis.readUnsignedShort();
                else if (tag == 3) dis.readInt();
                else if (tag == 4) dis.readFloat();
                else if (tag == 5) dis.readLong();
                else if (tag == 6) dis.readDouble();                
                else throw new ClassFormatError("Unbekannter Eintrag in Constant Pool: " + tag);
            }
            dis.readUnsignedShort(); //access flags
            int this_class_idx = dis.readUnsignedShort()-1;
            int name_idx = Integer.parseInt(constant_pool[this_class_idx]);
            sName = constant_pool[name_idx];
            if (sName != null) {
                sName = sName.replace('/', '.');
            }
            else throw new ClassFormatError("Klassenname wurde nicht gefunden!");
        }
        catch (EOFException ex) {
            throw new ClassFormatError(ex.getMessage());
        }
        catch (ArrayIndexOutOfBoundsException ex) {
            throw new ClassFormatError(ex.getMessage());
        }
        catch (NumberFormatException ex) {
            throw new ClassFormatError(ex.getMessage());
        }
        finally {
            try {
                fis.close();
            }
            catch (Throwable t) {}
        }
        return sName;
    }

Ich würde Variante 2 vorziehen, denn sie ist allgemeiner und verlässt sich nicht auf das ClassLoading.

Viel Erfolg!

Gruß,
Karl
 

Karl

Aktives Mitglied
Hallo,

@Bleiglanz
stimmt, nur ist javap wie so vieles nicht Bestandteil des JRE ;-)

Gruß,
Karl
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
J Suche: Tool zum Auffinden gleichnamiger Klassen (Name und Package gleich) in unteschiedlichen JARs Allgemeine Java-Themen 5
H JavaFX Warnung in package Zeile Allgemeine Java-Themen 2
jumichel Eclipse The package javax.mail is not accessible Allgemeine Java-Themen 3
M Mehrere Ressourcen in einem package ablegen Allgemeine Java-Themen 1
G Mac Package auslesen Allgemeine Java-Themen 17
F Reason: Missing Constraint: Import-Package: okhttp3.internal.http; version="0.0.0" Allgemeine Java-Themen 0
Tommy135 Input/Output Application aus Java package starten Allgemeine Java-Themen 2
J File in Package erstellen & lesen mit Programmstart in externe Projekt Allgemeine Java-Themen 3
B Maven Keycloak library wirft exceptions nach maven package Allgemeine Java-Themen 1
ReinerCoder auf Klassen innerhalb eines package zugreifen Allgemeine Java-Themen 22
T Plötzlich wird package nicht mehr gefunden Allgemeine Java-Themen 3
I Fehler beim Ant-Package erstellen mit Java 9 Allgemeine Java-Themen 1
K Classpath Alle Classen aus einem Package lesen Allgemeine Java-Themen 7
Sin137 Struktur der Klassen & Package Allgemeine Java-Themen 2
F Problem mit "package" Allgemeine Java-Themen 7
L Stack overflow bei einer endrekursiven Funktion (Anwendung: Spezialform des Package Merge) Allgemeine Java-Themen 4
D Classloader ohne Package Allgemeine Java-Themen 10
T Package durchsuchen Allgemeine Java-Themen 11
S leeres package obwohl inhalt da Allgemeine Java-Themen 53
S leeres Package nach neuinstallation des Pc Allgemeine Java-Themen 6
G Gleiche Packages in verschiedenen JAR Dateien - Welches Package wird verwendet? Allgemeine Java-Themen 5
D Package switching Allgemeine Java-Themen 7
G log4j package filter Allgemeine Java-Themen 10
M Klasse aus xyz.class Datei laden / package entfernen? Allgemeine Java-Themen 4
Bastifantasti Package installieren Allgemeine Java-Themen 2
G Package / Architektur Allgemeine Java-Themen 11
J package javax.servlet does not exist Allgemeine Java-Themen 5
M Dateien aus dem Package im Jar-File rauskopieren Allgemeine Java-Themen 3
V Zugriff auf Default-Package? Allgemeine Java-Themen 6
S Package in verschiedene Projekten einbinden? Allgemeine Java-Themen 3
J Kein Zugriff auf Klassen im Default Package Allgemeine Java-Themen 8
B J-Unit Tests. Alle Tests eines Package einsammen. Allgemeine Java-Themen 4
ARadauer Package Struktur Allgemeine Java-Themen 3
G bild in package Allgemeine Java-Themen 6
G Klasse aus Package auslesen Allgemeine Java-Themen 13
V Alle Klassen eines Package auflisten? Allgemeine Java-Themen 6
G jfreechart probleme mit dem package? Allgemeine Java-Themen 2
E (einfaches) Problem mit import und package (export) Allgemeine Java-Themen 4
E Was ist "default package" in Eclipse konkret? Allgemeine Java-Themen 12
M diff package? Allgemeine Java-Themen 7
T auf Klasse in Default package zugreifen Allgemeine Java-Themen 10
G externe package Allgemeine Java-Themen 7
A Package Probleme Allgemeine Java-Themen 9
J Konstruktor-Aufruf nur aus einem bestimmten Package erlauben Allgemeine Java-Themen 5
G Suche gutes Statistik Package Allgemeine Java-Themen 2
W Package via Reflection parsen Allgemeine Java-Themen 4
minzel ActionListener aus Package Allgemeine Java-Themen 24
P alle Klassen in package auflisten Allgemeine Java-Themen 2
M JNI: nach verschieben in package UnsatisfiedLinkError Allgemeine Java-Themen 3
D Laaaange Klassennamen und Package-Pfade. Allgemeine Java-Themen 5
J Einbinden einer protected-Methode aus anderem Package Allgemeine Java-Themen 2
H .java Dateien in anderem Package Allgemeine Java-Themen 8
S javadoc: package problem Allgemeine Java-Themen 3
G package und classpath grundsatzfrage Allgemeine Java-Themen 7
N Reflection: An Package einer .class-Datei kommen Allgemeine Java-Themen 2
T Problem: Ein Package für 2 Projekte? Allgemeine Java-Themen 3
S Problem bei Umstellung von (default package) auf Packages Allgemeine Java-Themen 10
G Java Package Allgemeine Java-Themen 2
EagleEye klassen package problem Allgemeine Java-Themen 3
C Jakarta commons package downloaden und installieren Allgemeine Java-Themen 7
L Package und Klassenname von aufrufender Klasse holen Allgemeine Java-Themen 2
Z auf static Methode aus anderen Package zugreifen? Allgemeine Java-Themen 7
H Klassen in einem Package ermitteln Allgemeine Java-Themen 6
C Problem mit Package Allgemeine Java-Themen 9
G Name des aktuellen Programms Allgemeine Java-Themen 7
L Ist ein string ein erlaubter variabel name? Allgemeine Java-Themen 2
S Variable als Objekt Name Allgemeine Java-Themen 3
J Apache POI - No external workbook with name Allgemeine Java-Themen 5
Neumi5694 Task-Name unter Windows Allgemeine Java-Themen 4
1 Name Generator für Videos Allgemeine Java-Themen 1
E Webservice zur Konvertierung IBAN/BIC -> Bank Name Allgemeine Java-Themen 1
P Name der Parent Klasse abfragen Allgemeine Java-Themen 8
D Name eines Nicht-String Objekts ausgeben Allgemeine Java-Themen 4
S Name einer Musikdatei auslesen und ändern Allgemeine Java-Themen 8
J IMDB Name und Bewertung auslesen Allgemeine Java-Themen 10
J .txt erstellen, nach name der vorhergehenden txt Allgemeine Java-Themen 7
P ActionListener / Label Name auslesen Allgemeine Java-Themen 2
S java -jar name.war. Wie Extraktionspfad umbiegen? Allgemeine Java-Themen 2
S [JUnit] Name von TestCase bekommen Allgemeine Java-Themen 4
D Passende Name für Methoden finden Allgemeine Java-Themen 3
Dit_ Registry, Preferences | Name des Knotens ändern. Allgemeine Java-Themen 2
E String name in class convertieren Allgemeine Java-Themen 4
E Variablen anderer Klassen auslesen (nur Name bekannt) Allgemeine Java-Themen 4
S Konstrukt Sinn, Zewck und Name Allgemeine Java-Themen 6
Ark Name für Funktion gesucht Allgemeine Java-Themen 5
D variabler Listen name Allgemeine Java-Themen 3
M Name der Swing Komponente Allgemeine Java-Themen 3
C Name einlesen und Programm starten Allgemeine Java-Themen 2
S "Guessed User name" bei Tomcat belegen Allgemeine Java-Themen 2
J Name eines Strings durch einen String festlegbar? Allgemeine Java-Themen 2
M Name von Wochentagen vergleichen Allgemeine Java-Themen 3
M Zugriff auf Objekt, Name in Variable Allgemeine Java-Themen 3
F Welcher Name? paintsXY(), isPaintXY(), isPaintingXY() . Allgemeine Java-Themen 4
V Objekt einer Klasse, deren Name nur als String vorhanden Allgemeine Java-Themen 4
D Name der Java-Applikation Allgemeine Java-Themen 2
A Class File zur Laufzeit laden ohne den Binary Name zu kennen Allgemeine Java-Themen 11
G jar-Name einer Klasse Allgemeine Java-Themen 9
O String übergeben ist name eines JTextField wie zugreifen Allgemeine Java-Themen 9
S Name der ausführenden jar-Datei abfragen Allgemeine Java-Themen 11
Y fehler: wrong name serverA Allgemeine Java-Themen 3

Ähnliche Java Themen

Neue Themen


Oben