![](/img/trans.png)
[英]Storing Byte Array inside an Object, and then converting it to ObjectOutputStream? (Stuck)
[英]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鍵。 在所有情況下,您的數據結構都需要將真實引用保存在垃圾回收器可以訪問的對象/數組中。
我認為您可以做的是:
`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;
`
對於Java中的內存數據結構,無法做到這一點。
jvm規范故意模糊了對象引用的存儲和分配方式,以允許不同的jvm實現對它們如何實現垃圾回收等做出不同的選擇。
最好的辦法(如果在內存中工作)是使用大字節數組模擬地址空間,在該空間中您將數組中的索引用作指針。
如果在磁盤上工作,那就不一樣了,因為可以通過偏移量訪問基於磁盤的存儲,並且指針很有意義,但是內存中的數據結構變得無關緊要
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.