Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to calculate a checksum for a Java class?

I have an application where I am generating a "target file" based on a Java "source" class. I want to regenerate the target when the source changes. I have decided the best way to do this would be to get a byte[] of the class contents and calculate a checksum on the byte[].

I am looking for the best way to get the byte[] for a class. This byte[] would be equivalent to the contents of the compiled .class file. Using ObjectOutputStream does not work. The code below generates a byte[] that is much smaller than the byte contents of the class file.

// 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;
}

Is there a way to get the byte[] with the identical contents of the *.class file? Calculating the checksum is the easy part, the hard part is obtaining the byte[] contents used to calculate an MD5 or CRC32 checksum.

like image 248
user2994892 Avatar asked Oct 20 '25 03:10

user2994892


1 Answers

THis is the solution that I ended up using. I don't know if it's the most efficient implementation, but the following code uses the class loader to get the location of the *.class file and reads its contents. For simplicity, I skipped buffering of the read.

// 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();
}
like image 110
user2994892 Avatar answered Oct 21 '25 17:10

user2994892



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!