2

I'm using Apache BCEL to dynamically create java classes that will each have its own associated image. These generated class implement the following interface:

interface ImageOwner {

    byte[] getImage();

}

When dynamically implementing the 'getImage' method, I could generate bytecodes to create/return the byte array when the method is invoked, but I would rather just return a reference to the byte array if possible. Is it possible to store raw data inside a java class file?

Thiago Padilha
  • 4,590
  • 5
  • 44
  • 69

5 Answers5

1

The only constants you can store in the constant pool are Ints, Floats, Longs, Doubles, Strings, and Classes. You're best bet is to just store it as a string and convert it to a Byte[] at run time. There is no need to base64 encode them, as strings can handle null characters, as long as you apply the proper modified unicode encoding.

Antimony
  • 37,781
  • 10
  • 100
  • 107
1

I'm really not sure here, because it seems too simple a question, but for completeness, this will do what I think you want to do:

public class ImageOwnerImpl implements ImageOwner {

    // A literal byte array. Tedious, but you could write code
    // to auto-generate this source from a file
    private byte[] imageByteArray = new byte[] { -128, 127, ...etc };

    public byte[] getImage() {
        return imageByteArray;
    }
}

This is a literal byte array, which answers your question of "how to store the bytes in the class file".

Most folks would load the image bytes from a file at runtime in the constructor, however you may have some special need that warrants this approach

Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • That's more or less what I need, but I don't want to invoke an external utility class in order to get the bytes, instead I want the bytes to be stored in the class file and retrieve it in the class body – Thiago Padilha Mar 24 '12 at 15:20
  • If what I want is not possible and you know for sure, just specify in the answer and I will mark as correct. – Thiago Padilha Mar 24 '12 at 15:21
  • @ThiadodeArruda I've edited the code to give an example of how to do it – Bohemian Mar 24 '12 at 15:30
  • 1
    The problem with this approach is that this new byte array is actually created in the constructor, which will not only allocate the array, but also emit opcodes to store each byte which is what I was trying to avoid. Since the jvm only operated with 4 byte integers, a byte array stored like this would at least use 4x its actual space, without even considering the bytecodes necessary to create the byte array and store each byte on its own slot. This can be bad for large image files. – Thiago Padilha Mar 24 '12 at 15:44
1

After some research, the best way I found to achieve my needs was to base64 encode the image data and use the constant pool to store the resulting String. Even with the =~ 30% loss, it seems better than using the constructor or other methods to initialize a byte array field.

Thiago Padilha
  • 4,590
  • 5
  • 44
  • 69
0

You could just store it as a byte array the syntax for array in BCEL is

[B

for byte array

[java.lang.String

for a string array etc.

ILOVEPIE
  • 177
  • 1
  • 10
0

Just define an Impl class that has a static initialiser that loads the raw data from a file that is included in your jar and loaded via the classloader.

pauljwilliams
  • 19,079
  • 3
  • 51
  • 79