我有一个字节数组和一个对象引用。
byte[] data = new byte[128];
Block b = new Block();
我想将参考b存储在“data”数组的最后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个字节 block将指向第5个块,并指向第5个块的最后2个字节 第6块等等。
答案 0 :(得分:5)
基本上,数据数组将使用126个字节来存储字符串,并使用最后两个(或4个)字节来存储对另一个块的引用。它的链接列表。
您可以通过存储阻止索引来完成此操作。
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;
我可以使用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的预算。
答案 1 :(得分:1)
您可以通过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();
答案 2 :(得分:1)
我需要存储一个引用新块的指针(引用)。
基本上,你不能在纯Java中完成这项工作。
非纯Java方法(使用JNI或Unsafe
类)将为您提供一个不能安全地转回Java引用的值。
原因是当GC运行时,它通常将可到达的对象移动到新位置。现在,如果您在正确的引用类型字段,变量或数组槽中引用了一个对象,GC将找到该引用副本并将其更新为指向该对象的新位置。但是如果引用已经转换为字节或其他内容,那么GC将不知道字节实际上是引用的表示,并且不会更新它。因此,您的reference-represent-as-bytes现在将指向错误的位置。如果你把它变成参考并尝试使用它,可能会发生混乱。
您需要找到一种不同的方式来表示这些Block
引用。如果您不愿意自己序列化Block
个对象,那么显而易见的选项是某种索引或Map键。在所有情况下,您的数据结构都需要保存垃圾收集器可以访问的对象/数组中的实际引用。
答案 3 :(得分:0)
我认为你所做的是:
` 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;
`
答案 4 :(得分:0)
对于java中的内存数据结构,无法做到这一点。
jvm规范故意模糊了如何存储和分配对象引用,以允许不同的jvm实现对它们如何实现垃圾收集做出不同的选择等。
你可以做的最好的事情(如果在内存中工作)是模拟一个带有大字节数组的地址空间,你在这里使用数组中的索引作为指针。
如果在磁盘上工作,这是一个不同的故事,因为基于磁盘的存储可以通过偏移和指针访问,但是你的内存数据结构变得无关紧要