3

Java「ソース」クラスに基づいて「ターゲット ファイル」を生成するアプリケーションがあります。ソースが変更されたときにターゲットを再生成したい。これを行う最善の方法は、クラス コンテンツの byte[] を取得し、byte[] のチェックサムを計算することであると判断しました。

クラスの byte[] を取得する最良の方法を探しています。この byte[] は、コンパイルされた .class ファイルの内容に相当します。ObjectOutputStream を使用しても機能しませ。以下のコードは、クラス ファイルのバイト コンテンツよりもはるかに小さい byte[] を生成します。

// Incorrect function to calculate the byte[] contents of a Java class
public static final byte[] getClassContents(Class<?> myClass) throws IOException {
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    try( ObjectOutputStream stream = new ObjectOutputStream(buffer) ) {
        stream.writeObject(myClass);
    }
    // This byte array is much smaller than the contents of the *.class file!!!
    byte[] contents = buffer.toByteArray();
    return contents;
}

*.class ファイルと同じ内容の byte[] を取得する方法はありますか? チェックサムの計算は簡単ですが、難しいのは、MD5 または CRC32 チェックサムの計算に使用される byte[] の内容を取得することです。

4

3 に答える 3

4

これは私が最終的に使用したソリューションです。これが最も効率的な実装かどうかはわかりませんが、次のコードはクラス ローダーを使用して *.class ファイルの場所を取得し、その内容を読み取ります。簡単にするために、読み取りのバッファリングをスキップしました。

// Function to obtain the byte[] contents of a Java class
public static final byte[] getClassContents(Class<?> myClass) throws IOException {
    String path = myClass.getName().replace('.', '/');
    String fileName = new StringBuffer(path).append(".class").toString();
    URL url = myClass.getClassLoader().getResource(fileName);
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    try (InputStream stream = url.openConnection().getInputStream()) {
        int datum = stream.read();
        while( datum != -1) {
            buffer.write(datum);
            datum = stream.read();
        }
    }   
    return buffer.toByteArray();
}
于 2013-11-15T14:50:39.817 に答える
0

本当に .class ファイルの内容が必要な場合は、メモリ内の byte[] 表現ではなく、.class ファイルの内容を読み取る必要があります。だから何か

import java.io.*;

public class ReadSelf {
    public static void main(String args[]) throws Exception  {
        Class classInstance = ReadSelf.class;
        byte[] bytes = readClass(classInstance);
    }
    public static byte[] readClass(Class classInstance) throws Exception {
        String name = classInstance.getName();
        name = name.replaceAll("[.]", "/") + ".class";
        System.out.println("Reading this: " + name);
        File file = new File(name);
        System.out.println("exists: " + file.exists());
        return read(file);
    }
    public static byte[] read(File file) throws Exception {
        byte[] data = new byte[(int)file.length()]; // can only read a file of size INT_MAX
        DataInputStream inputStream =
        new DataInputStream(
            new BufferedInputStream(
                new FileInputStream(file)));

        int total = 0;
        int nRead = 0;
        try {
            while((nRead = inputStream.read(data)) != -1) {
                total += nRead;
            }
        }
        finally {
            inputStream.close();
        }
        System.out.println("Read " + total
            + " characters, which should match file length of "
            + file.length() + " characters");
        return data;
    }
}
于 2013-11-15T07:58:06.840 に答える