我有以下Javolution的实现:
public class RunScan extends Struct
{
public final Signed32 numOfClusters = new Signed32();
public final ClusterData[] clusters;
public final Signed32 numOfRecons = new Signed32();
public final ReconData[] recons ;
public RunScan (int numOfClusters, int numOfRecons)
{
this.numOfClusters.set(numOfClusters);
this.numOfRecons.set(numOfRecons);
clusters = array(new ClusterData[numOfClusters]);
recons = array(new ReconData[numOfRecons]);
}
}
public class ClusterData extends Struct
{
public final UTF8String scanType = new UTF8String(CommInterfaceFieldConstants.SCAN_TYPE_SIZE);
public final UTF8String patientId = new UTF8String(CommInterfaceFieldConstants.PATIENT_ID_SIZE);
.
.
.
}
public class ReconData extends Struct
{
public final UTF8String patientId = new UTF8String(CommInterfaceFieldConstants.PATIENT_ID_SIZE);
public final UTF8String scanSeriesId = new UTF8String(CommInterfaceFieldConstants.SCAN_SERIES_ID_SIZE);
.
.
.
}在我们的通信类中,在将数据放入套接字之前,我们需要获取RunScan对象的bytes[],但我们在“//<”行中获取了BufferUnderflowException:
private byte[] getCmdBytes(Struct scCmd)
{
ByteBuffer cmdBuffer = scCmd.getByteBuffer();
int cmdSize = scCmd.size();
byte[] cmdBytes = new byte[cmdSize];
if (cmdBuffer.hasArray())
{
int offset = cmdBuffer.arrayOffset() + scCmd.getByteBufferPosition();
System.arraycopy(cmdBuffer.array(), offset, cmdBytes, 0, cmdSize);
}
else
{
String msg = "\n\ncmdBufferRemaining=" + cmdBuffer.remaining() + ", cmdBytesSize=" + cmdBytes.length + "\n\n";
System.out.println(msg);
cmdBuffer.position(scCmd.getByteBufferPosition());
cmdBuffer.get(cmdBytes); //<<<<<<<<<< underFlowException
}
return cmdBytes;
}此方法适用于其他情况。发生异常是因为这一行,
ByteBuffer cmdBuffer = scCmd.getByteBuffer();只返回RunScan对象的8个字节的ByteBuffer (来自剩余的()方法),我想这两个字段是Signed32字段。但是这一行,
int cmdSize = scCmd.size();返回RunScan对象的正确长度,包括这两个数组的大小。
如果我在声明这两个数组(不是构造函数中的"new“数组)时用硬编码的长度创建它们,它工作得很好,没有任何异常。
有人能帮我找出我们的实现出了什么问题吗?
发布于 2011-08-03 22:33:08
我的代码也遇到了类似的情况。通常,对于当前的Struct对象,不能在与包含数组中元素数量的成员相同的结构中定义可变长度数组。
尝试如下所示:
public class RunScanHeader extends Struct
{
public final Signed32 numOfClusters = new Signed32();
public final Signed32 numOfRecons = new Signed32();
}
public class RunScanBody extends Struct
{
public final ClusterData[] clusters;
public final ReconData[] recons ;
public RunScan (int numOfClusters, int numOfRecons)
{
clusters = array(new ClusterData[numOfClusters]);
recons = array(new ReconData[numOfRecons]);
}
}然后,您将需要一个两阶段的方法来读写,首先读/写头部数据,然后读/写主体数据。
很抱歉,我现在没有更多的细节,如果你不能解决这个问题,请让我知道,我会深入研究我的代码。
发布于 2011-08-09 04:31:37
初始化顺序很重要,因为它定义了每个字段的位置。初始化是在声明字段时完成的(最常见的情况)。或者,如果在构造函数中执行此操作,则必须记住构造函数是在成员初始化之后调用的。下面是一个在构造函数中完成初始化的示例:
public class RunScan extends Struct {
public final Signed32 numOfClusters;
public final ClusterData[] clusters;
public final Signed32 numOfRecons;
public final ReconData[] recons ;
public RunScan (int numOfClusters, int numOfRecons) {
// Initialization done in the constructor for all members
// Order is important, it should match the declarative order to ensure proper positioning.
this.numOfClusters = new Signed32();
this.clusters = array(new ClusterData[numOfClusters]);
this.numOfRecons = new Signed32();
this.recons = array(new ReconData[numOfRecons]);
// Only after all the members have been initialized the set method can be used.
this.numOfClusters.set(numOfClusters);
this.numOfRecons.set(numOfRecons);
}
}发布于 2011-08-09 05:24:02
get()将移动ByteBuffer的位置。
scCmd.getByteBuffer().slice().get(dest)可能会解决移动位置和意外副作用的问题。
如果slice()生成错误的原始缓冲区图片,scCmd.getByteBuffer().duplicate().get(dest)也可以解决您的问题。
此外,看起来好像scCmd.getByteBuffer()创建了一个冗余引用,而您正在使用相同的方法调用源引用和子引用。
如果scCmd.getByteBuffer()已经向您传递了一个slice(),那么您对这些方法的冗余访问肯定会做一些与您计划不同的事情。
https://stackoverflow.com/questions/6914430
复制相似问题