Определите классы, на которые есть ссылки в файле .class - PullRequest
4 голосов
/ 18 ноября 2009

Каков наилучший способ (программно) проанализировать скомпилированный файл Java (.class) и сгенерировать список любых других Java-классов, на которые он ссылается?

Ответы [ 5 ]

7 голосов
/ 18 ноября 2009

Легко сделать это самостоятельно, если вы знаете спецификацию .

Вот быстрая и грязная демонстрационная программа, как это сделать:

package test;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class Main {

    private static Map<Integer, String> strings = new HashMap<Integer, String>();
    private static Set<Integer> classes = new HashSet<Integer>();
    private static int indexCorrection = 0; // for correcting indexes to constant pools with long and double entries

    public static void main(String[] args) throws Exception {
        printReferencedClassesFromClass(String.class);
    }

    private static void printReferencedClassesFromClass(Class<?> c) throws IOException {
        saveReferencedClassesFromStream(c.getResourceAsStream(c.getSimpleName() + ".class"));
        printReferencedClasses();
    }

    private static void printReferencedClasses() {
        for (Integer index : classes)
            System.out.println(strings.get(index));
    }

    private static void saveReferencedClassesFromStream(InputStream stream) throws IOException {
        DataInputStream dataStream = new DataInputStream(stream);
        skipHeader(dataStream);
        saveReferencedClassesFromConstantPool(dataStream);
    }

    private static void skipHeader(DataInputStream dataInputStream) throws IOException {
        readU4(dataInputStream); // magic byte
        readU2(dataInputStream); // minor version
        readU2(dataInputStream); // major version
    }

    private static void saveReferencedClassesFromConstantPool(DataInputStream stream) throws IOException {
        int poolSize = readU2(stream);
        for (int n = 1; n < poolSize - indexCorrection; n++)
            savePoolEntryIfIsClassReference(n, stream);
    }

    private static void savePoolEntryIfIsClassReference(int index, DataInputStream stream) throws IOException {
        int tag = readU1(stream);
        switch (tag) {
        case 1: // Utf8
            saveStringFromUtf8Entry(index, stream);
            break;
        case 7: // Class
            saveClassEntry(stream);
            break;
        case 8: // String
        case 16: // MethodType
            readU2(stream);
            break;
        case 3: // Integer
        case 4: // Float
            readU4(stream);
            break;
        case 5: // Long
        case 6: // Double
            readU4(stream);
            readU4(stream);
            indexCorrection++;
            break;
        case 9: // Fieldref
        case 10: // Methodref
        case 11: // InterfaceMethodref
        case 12: // NameAndType
        case 18: // InvokeDynmaic
            readU2(stream);
            readU2(stream);
            break;
        case 15: // MethodHandle
            readU1(stream);
            readU2(stream);
            break;
        }
    }

    private static void saveClassEntry(DataInputStream stream) throws IOException {
        classes.add(readU2(stream));
    }

    private static void saveStringFromUtf8Entry(int index, DataInputStream stream) throws IOException {
        strings.put(index + indexCorrection, readString(stream));
    }

    private static String readString(DataInputStream stream) throws IOException {
        return stream.readUTF();
    }

    private static int readU1(DataInputStream stream) throws IOException {
        return stream.readUnsignedByte();
    }

    private static int readU2(DataInputStream stream) throws IOException {
        return stream.readUnsignedShort();
    }

    private static int readU4(DataInputStream stream) throws IOException {
        return stream.readInt();
    }

}

Вывод:

test/Main
java/lang/Object
java/io/BufferedInputStream
java/util/Iterator
java/io/FileInputStream
java/lang/System
java/lang/Integer
java/lang/Exception
java/lang/String
java/io/File
java/util/Map
java/util/HashMap
java/io/IOException
java/util/Set
java/io/DataInputStream
java/io/PrintStream
java/util/HashSet
java/lang/Throwable
1 голос
/ 18 ноября 2009

Это можно сделать с помощью Apache BCEL .

1 голос
/ 18 ноября 2009

Вы пробовали JDepend? Он анализирует файлы классов для определения ссылок.

0 голосов
/ 18 мая 2012

Я думаю, вы можете использовать мой Java Respendency Resolver , который найдет не только ссылочные java-файлы, но также jar-файлы для определенного класса в Project

0 голосов
/ 18 ноября 2009

Я не знаю, как лучше. Я знаю, что есть 2 API, которые могут помочь.

Вы можете попробовать jclasslib для проверки файлов .class
http://www.ej -technologies.com / Продукты / jclasslib / resources.html
или BCEL (библиотека разработки байт-кода) для анализа и обработки файлов .class.
http://jakarta.apache.org/bcel/

Насколько я понимаю, любой класс, который будет использоваться в .class (в том числе поле, параметр, тип возвращаемого значения и т. Д.), Определен в constant_pool. Так что вы можете прочитать об этом.
http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...