简体   繁体   English

将对象引用存储在字节数组中

[英]storing an object reference in byte array

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. 我想将引用b存储在“数据”数组的最后2个(或4个)字节中。

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 我的Block类如下

    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. 基本上,数据数组将使用126个字节存储字符串,最后两个(或4个)字节存储对另一个块的引用。 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. 我本可以使用Block类的不同定义来完成此操作的(通过在类本身中包括对Block的引用)。但是问题声明指出了约束,即只能将最后2个字节用作对另一个块的引用。 from other post I came to know that in jvm(32-bit) a reference is of size 4 bytes. 从其他帖子中,我知道在jvm(32位)中,引用的大小为4个字节。 Hence I think it can be only done using last 4 bytes 因此,我认为只能使用最后4个字节来完成

Snippet from problem statement 问题陈述的摘录

the last 2 bytes of the block is used to point to the next block . 该块的最后2个字节用于指向下一个块。 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. 假设文件大小为8块,则第4个块的后2个字节将指向第5个块,第5个块的后2个字节将指向第6个块,依此类推。

Basically the data array will use 126 byte to store a String and last two( or 4) bytes to store reference to another block. 基本上,数据数组将使用126个字节存储字符串,最后两个(或4个)字节存储对另一个块的引用。 Its kind of Link List. 它的链接列表。

You can do this by storing a Block index. 您可以通过存储块索引来做到这一点。

eg 例如

// 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. 我本可以使用Block类的不同定义来完成此操作的(通过在类本身中包括对Block的引用)。但是问题声明指出了约束,即只能将最后2个字节用作对另一个块的引用。 from other post I came to know that in jvm(32-bit) a reference is of size 4 bytes. 从其他帖子中,我知道在jvm(32位)中,引用的大小为4个字节。 Hence I think it can be only done using last 4 bytes 因此,我认为只能使用最后4个字节来完成

All 32-bit systems use 32-bit pointers or references. 所有32位系统都使用32位指针或引用。 You can't places an reference in Java because there is no global way of referring to an object via a number. 您无法在Java中放置引用,因为没有通过数字引用对象的全局方法。 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 7,可以使用的最小内存约为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. 这意味着您甚至在程序启动之前就已经使用了超过1 MB的预算。

You can serialize any object via ObjectOutputStream (Note that you must add implements Serializable to your class Block ). 您可以通过ObjectOutputStream序列化任何对象(请注意,必须将implements Serializable添加到类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();

I need to store a pointer( reference) referencing to a new block. 我需要存储一个引用新块的指针(引用)。

Basically, you cannot do this at all in pure Java. 基本上,您不能在纯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. 而且非纯Java方法(使用JNI或Unsafe类)将为您提供一个值,您无法安全地将其转换回Java引用。

The reason is that when the GC runs, it will typically move reachable objects to new locations. 原因是,GC运行时,通常会将可到达的对象移动到新位置。 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. 现在,如果您在适当的引用类型的字段,变量或数组插槽中具有对对象的引用,GC将找到该引用副本并将其更新以指向该对象的新位置。 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. 但是,如果将引用转换为字节或其他形式,则GC将不会知道字节实际上是引用的表示形式,因此也不会对其进行更新。 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. 您需要找到其他方式来表示这些Block引用。 If you are not willing to serialize the Block objects themselves, the obvious options are indexes or Map keys of some kind. 如果您不愿意序列化Block对象本身,则显而易见的选项是某种索引或Map键。 In all cases, your data structure will need to hold the real references in objects / arrays that are reachable by the garbage collector. 在所有情况下,您的数据结构都需要将真实引用保存在垃圾回收器可以访问的对象/数组中。

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) {// `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. 使用System.arraycopy (src,srcPos,dest,destPos,length)方法从源对象复制到目标对象。

This cannot be done for an in-memory data structure in java. 对于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. jvm规范故意模糊了对象引用的存储和分配方式,以允许不同的jvm实现对它们如何实现垃圾回收等做出不同的选择。

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 如果在磁盘上工作,那就不一样了,因为可以通过偏移量访问基于磁盘的存储,并且指针很有意义,但是内存中的数据结构变得无关紧要

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM