2

I have a byte array and an object reference.

    byte[] data = new byte[128];

    Block b = new Block();

I want to store reference b in last 2 (or 4) bytes of "data" array.

Kindly Note: I dont want to serialize the object and store in byte array. I need to store a pointer( reference) referencing to a new block.

EDIT

My Block class is as follows

    public class Block {
        byte[] data ;

        public Block(){
            data = new byte[128];
        }
}

Basically the data array will use 126 byte to store a String and last two( or 4) bytes to store reference to another block. Its kind of Link List.

I could have done it using a different definition of Block class [By including reference to Block in class itself].. But problem statement states the constraint that only last 2 bytes should be used as a reference to another block. from other post I came to know that in jvm(32-bit) a reference is of size 4 bytes. Hence I think it can be only done using last 4 bytes

Snippet from problem statement

the last 2 bytes of the block is used to point to the next block . Suppose if the file is of 8 block size, then the last 2 bytes of 4th block will point to 5th block and last 2 bytes of 5th block points to 6th block and so on.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
Anupam Gupta
  • 1,591
  • 8
  • 36
  • 60
  • 1
    I believe you cannot get a reference address of an object. – nullpotent Sep 16 '12 at 13:17
  • What do you intend to do with that 2/4 byte reference? – Vikdor Sep 16 '12 at 13:17
  • Please state what you will do with the byte array. If you're sending it to a file or another application via sockets or IPC, keeping a reference that only makes sense in the application itself, in that running process, is useless. – E_net4 Sep 16 '12 at 13:31
  • @E_net4 Edited question with snippet from problem statement – Anupam Gupta Sep 16 '12 at 13:32
  • Some context as to why you would want to do this would help because what you are trying to do doesn't make much sense to do in memory. It could be used as a Serialization format or memory mapped data but not if you are using objects which you appear to be doing. – Peter Lawrey Sep 16 '12 at 13:39
  • @PeterLawrey Kindly refer the copied snippet from problem-statement in my question. I am writing a program for a problem statement which restricts my overall memory usage and limits it to 1MB. Since the constraints mentioned in problem statement states the use of last few bytes to store pointer to next block, I am forced to implement it this way – Anupam Gupta Sep 16 '12 at 13:44
  • In that case you are sunk because Java will not run with 1 MB of memory, not even a program which doesn't do anything. It appears your requirement were written for another language because they don't make sense unless you have an embedded device (which wont support Java). BTW your Block object takes 16 bytes and your `byte[]` take another 16 bytes over and above the `128` bytes you allocated. BTW Java doesn't have pointers by design. – Peter Lawrey Sep 16 '12 at 13:48
  • Even if you has a C program, to address 1 MB you need 20-bit addresses which requires more than 2 bytes, unless you have an 8086 which was popular 30 years ago, and it could address up to 1 MB of memory using a combination of 16-bit address. Is the puzzle 30 years old? – Peter Lawrey Sep 16 '12 at 13:52
  • 1
    @PeterLawrey :-D I am not sure how old is puzzle. But after reading posts here, I am pretty confident to use a reference-to-Block in my class definition – Anupam Gupta Sep 16 '12 at 14:06
  • A more realistic limit these days might be 1 GB which is still only $10 is a modern PC. – Peter Lawrey Sep 16 '12 at 14:11
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/16747/discussion-between-anupam-gupta-and-peter-lawrey) – Anupam Gupta Sep 16 '12 at 22:45
  • I am sorry, was asleep 7 hours ago. ;) – Peter Lawrey Sep 17 '12 at 06:07

5 Answers5

5

Basically the data array will use 126 byte to store a String and last two( or 4) bytes to store reference to another block. Its kind of Link List.

You can do this by storing a Block index.

e.g

// list of blocks so you can lookup any block using a 16-bit index.
List<Block> blocks = new ArrayList<Block>();

int indexInBlocksToNext = ...
data[126] = (byte) (indexInBlocksToNext >> 8);
data[127] = (byte) indexInBlocksToNext;

I could have done it using a different definition of Block class [By including reference to Block in class itself].. But problem statement states the constraint that only last 2 bytes should be used as a reference to another block. from other post I came to know that in jvm(32-bit) a reference is of size 4 bytes. Hence I think it can be only done using last 4 bytes

All 32-bit systems use 32-bit pointers or references. You can't places an reference in Java because there is no global way of referring to an object via a number. You can obtain where an object was in memory, but this location can change at any time.


With Java 7 the minimum memory used before you can start is about 1.3 MB.

$ java -mx1200k -version
Error occurred during initialization of VM
Too small initial heap for new size specified
$ java -mx1300k -version
java version "1.7.0_05"
Java(TM) SE Runtime Environment (build 1.7.0_05-b05)
Java HotSpot(TM) 64-Bit Server VM (build 23.1-b03, mixed mode)

This means you have used more than your budget of 1 MB before your program even starts.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • +1 `You can obtain where an object was in memory` ummm, how can this be done in Java? – Eng.Fouad Sep 16 '12 at 13:39
  • 2
    You can use JNI or `sun.misc.Unsafe` to obtain the reference as in `int` or `long` value to see its location but this only tells you where it was because by the time you have the number it could have changed. For 64-bit JVMs it doesn't really tell you the absolute location because it uses 32-bit references for up to 32 GB of memory and can use a translated such as `reference * 8 + offset` to get the actual location in memory. – Peter Lawrey Sep 16 '12 at 13:41
  • But really, you should never ever do this. – Louis Wasserman Sep 16 '12 at 16:31
  • 1
    You shouldn't believe you have a need to do this. ;) – Peter Lawrey Sep 16 '12 at 16:49
1

You can serialize any object via ObjectOutputStream (Note that you must add implements Serializable to your class Block). For example:

Block block = new Block();
// ...
ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(new File("test.dat"))));
oos.wrtieObject(block);
oos.close();

and then read it like:

ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream(new File("test.dat"))));
Block block = (Block) ois.readObject();
ois.close();
Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417
  • That's what I thought he asked about. – nullpotent Sep 16 '12 at 13:18
  • how it will help? What I will do with the searialized object. I dont want to store object in byte array. I want to store Object reference in byte array. – Anupam Gupta Sep 16 '12 at 13:19
  • What for? I'm pretty sure it can be done using some interface, or language mechanism. – Krzysztof Jabłoński Sep 16 '12 at 13:21
  • 1
    You won't be able to do that in a clean way. Even if you do, you won't be able to do much with it. This might be of help though, do read this document. http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/sun/misc/Unsafe.java#Unsafe – nullpotent Sep 16 '12 at 13:21
  • @AnupamGupta I am not sure what you are trying to do. References cannot be stored. When you assign reference `A` to reference `B` like `B = A;`, this will make `B` pointing to the object that `A` is pointing to! See [this answer](http://stackoverflow.com/a/12444216/597657), and [this one](http://stackoverflow.com/a/9404727/597657) for more information. – Eng.Fouad Sep 16 '12 at 13:27
  • Thanks @Eng.Fouad for answering the question. But the problem statement has put the constraint of using 2 bytes for storing reference. – Anupam Gupta Sep 16 '12 at 13:30
  • 1
    @AnupamGupta as iccthedral mentioned, you cannot access the reference address (memory location) of an object! At least not in Java :) – Eng.Fouad Sep 16 '12 at 13:33
1

I need to store a pointer( reference) referencing to a new block.

Basically, you cannot do this at all in pure Java.

And the non-pure Java ways to do this (using JNI or the Unsafe class) will give you a value that you cannot safely turn back into a Java reference.

The reason is that when the GC runs, it will typically move reachable objects to new locations. Now if you have a reference to an object in a proper reference-typed field, variable or array slot, the GC will find that reference copy and update it to point to the object's new location. But if the reference has been turned into bytes or something else, then the GC won't know that the bytes are actually a representation of a reference, and won't update it. So your reference-represented-as-bytes will now point to the wrong place. If you turn it back into a reference and attempt to use it, mayhem is likely to ensue.


You need to find a different way to denote these Block references. If you are not willing to serialize the Block objects themselves, the obvious options are indexes or Map keys of some kind. In all cases, your data structure will need to hold the real references in objects / arrays that are reachable by the garbage collector.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
0

I think what you ca do is:

  1. first Serialize Block Class.
  2. then using something like following to convert block object to byte array.

` public byte[] toByteArray(Object obj) {//

    byte[] bytes = null;
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    try {
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(obj);
        oos.flush();
        oos.close();
        bos.close();
        bytes = bos.toByteArray();
    } catch (IOException ex) {
        System.out.println(ex);
    }
    return bytes;

`

  1. Use System.arraycopy(src, srcPos, dest, destPos, length) method to copy from source object to destination object.
Iman
  • 381
  • 1
  • 5
  • Firstly, you can not serialize a class. only an object can be serialized.Kindly note that I don't need to serialize object. I need to store reference of an Object in bytes..Which as of now (from other answer ) is not possible in java – Anupam Gupta Sep 16 '12 at 13:38
0

This cannot be done for an in-memory data structure in java.

The jvm specification is deliberately vague about how object references are stored and allocated in order to allow different jvm implementations to make different choices as to how they implement garbage collection, etc.

The best you can do (if working in memory) is to emulate an address space with a large byte array, where you are using the index in the array as a pointer.

If working on disk, that is a different story as disk based storage is accessible by offset and pointers make sense but your in-memory data structure becomes irrelevant

Stephen Connolly
  • 13,872
  • 6
  • 41
  • 63
  • There was a way to do this with block memory mapping a file (and only store it on purpose). But yet again a file pointer is different. – Martin Kersten Feb 06 '15 at 14:40