簡體   English   中英

將對象引用存儲在字節數組中

[英]storing an object reference in byte array

我有一個字節數組和一個對象引用。

    byte[] data = new byte[128];

    Block b = new Block();

我想將引用b存儲在“數據”數組的最后2個(或4個)字節中。

請注意:我不想序列化對象並存儲在字節數組中。 我需要存儲一個引用新塊的指針(引用)。

編輯

我的Block類如下

    public class Block {
        byte[] data ;

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

基本上,數據數組將使用126個字節存儲字符串,最后兩個(或4個)字節存儲對另一個塊的引用。 它的鏈接列表。

我本可以使用Block類的不同定義來完成此操作的(通過在類本身中包括對Block的引用)。但是問題聲明指出了約束,即只能將最后2個字節用作對另一個塊的引用。 從其他帖子中,我知道在jvm(32位)中,引用的大小為4個字節。 因此,我認為只能使用最后4個字節來完成

問題陳述的摘錄

該塊的最后2個字節用於指向下一個塊。 假設文件大小為8塊,則第4個塊的后2個字節將指向第5個塊,第5個塊的后2個字節將指向第6個塊,依此類推。

基本上,數據數組將使用126個字節存儲字符串,最后兩個(或4個)字節存儲對另一個塊的引用。 它的鏈接列表。

您可以通過存儲塊索引來做到這一點。

例如

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

我本可以使用Block類的不同定義來完成此操作的(通過在類本身中包括對Block的引用)。但是問題聲明指出了約束,即只能將最后2個字節用作對另一個塊的引用。 從其他帖子中,我知道在jvm(32位)中,引用的大小為4個字節。 因此,我認為只能使用最后4個字節來完成

所有32位系統都使用32位指針或引用。 您無法在Java中放置引用,因為沒有通過數字引用對象的全局方法。 您可以獲取對象在內存中的位置,但是此位置可以隨時更改。


對於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)

這意味着您甚至在程序啟動之前就已經使用了超過1 MB的預算。

您可以通過ObjectOutputStream序列化任何對象(請注意,必須將implements Serializable添加到類Block )。 例如:

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

然后像這樣閱讀:

ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream(new File("test.dat"))));
Block block = (Block) ois.readObject();
ois.close();

我需要存儲一個引用新塊的指針(引用)。

基本上,您不能在純Java中完全做到這一點。

而且非純Java方法(使用JNI或Unsafe類)將為您提供一個值,您無法安全地將其轉換回Java引用。

原因是,GC運行時,通常會將可到達的對象移動到新位置。 現在,如果您在適當的引用類型的字段,變量或數組插槽中具有對對象的引用,GC將找到該引用副本並將其更新以指向該對象的新位置。 但是,如果將引用轉換為字節或其他形式,則GC將不會知道字節實際上是引用的表示形式,因此也不會對其進行更新。 因此,您的“以字節為單位的引用表示”現在將指向錯誤的位置。 如果將其轉換為參考並嘗試使用它,則可能會發生混亂。


您需要找到其他方式來表示這些Block引用。 如果您不願意序列化Block對象本身,則顯而易見的選項是某種索引或Map鍵。 在所有情況下,您的數據結構都需要將真實引用保存在垃圾回收器可以訪問的對象/數組中。

我認為您可以做的是:

  1. 首先序列化塊類。
  2. 然后使用類似下面的方法將塊對象轉換為字節數組。

`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. 使用System.arraycopy (src,srcPos,dest,destPos,length)方法從源對象復制到目標對象。

對於Java中的內存數據結構,無法做到這一點。

jvm規范故意模糊了對象引用的存儲和分配方式,以允許不同的jvm實現對它們如何實現垃圾回收等做出不同的選擇。

最好的辦法(如果在內存中工作)是使用大字節數組模擬地址空間,在該空間中您將數組中的索引用作指針。

如果在磁盤上工作,那就不一樣了,因為可以通過偏移量訪問基於磁盤的存儲,並且指針很有意義,但是內存中的數據結構變得無關緊要

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM