0

In one data class, class A, I have the following:

class A
{
    private byte[] coverInfo = new byte[CoverInfo.SIZE];

    private ByteBuffer coverInfoByteBuffer = ByteBuffer.wrap(coverInfo);
    ...
}

In a CoverInfo class, I have few fields:

class CoverInfo
{    
    public static final int SIZE = 48;

    private byte[] name = new byte[DataConstants.Cover_NameLength];
    private byte[] id = new byte[DataConstants.Cover_IdLength];
    private byte[] sex = new byte[DataConstants.Cover_SexLength];
    private byte[] age = new byte[DataConstants.Cover_AgeLength];

}

When class A get the coverInfo data, I create an instance of CoverInfo and and populate data into the CoverInfo object like this inside the Class A:

public void createCoverInfo()
{
    CoverInfo tempObj = new CoverInfo();
    tempObj.populate(coverInfoByteBuffer);
    ....
}

In the populate() method of the CoverInfo class, I have the following:

public void populate(ByteBuffer dataBuf)
{
    dataBuf.rewind();

    dataBuf.get(name, 0, DataConstants.Cover_NameLength);
    dataBuf.get(id, 0, DataConstants.Cover_IdLength);
    dataBuf.get(sex, 0, DataConstants.Cover_SexLength);
    dataBuf.get(age, 0, DataConstants.Cover_AgeLength);
}

The populate() method will throw exception on Windows (always) but it works on Linux:

java.nio.BufferUnderflowException
    java.nio.HeapByteBuffer.get(HeapByteBuffer.java:151)
    com.bowing.uiapp.common.socketdata.message.out.CoverInfo.populate(CoverInfo.java:110)

And the Exception line number is not fixed in one line.

It is running on multiple threads environment.

If I use a duplicated (read-only is fine) ByteBuffer, the issue resolved:

tempObj.populate(coverInfoByteBuffer.duplicate());

Few questions about this:

  1. why it works on Linux but not on Windows (just a timing issue)?
  2. I guess the issue is caused by the limit/position/mark values are changed by others while this CoverInfo object is accessing the ByteBuffer, the duplicate() is the preferred way for this situation?
  3. If the ByteBuffer's slice() is used, how to guarantee data integrity if more than one user to modify the ByteBuffer?
  4. how to use ByteBuffer properly in multiple thread environment?

2 Answers 2

2

From the Javadoc of the Buffer class:

Thread safety

Buffers are not safe for use by multiple concurrent threads. If a buffer is to be used by more than one thread then access to the buffer should be controlled by appropriate synchronization.

That's what the spec says. As you said, creating multiple views of the buffer with their own independent positions, etc. can work. Also, using absolute reads (where you specify a position) might also work. None of these are guaranteed to work according to the documentation and might work only on some buffer implementations.

Sign up to request clarification or add additional context in comments.

1 Comment

"None of these are guaranteed to work according to the documentation and might work only on some buffer implementations." --- are you saying there is no real solution?
1

I'm guess the problem is that you have multiple threads all trying to work on the buffer at the same time, despite none of them modifying the data in the buffer they are changing the state of the buffer specifically the read/write position.

Solutions:

Only allow one thread at a time to interact with the buffer...

public void populate(ByteBuffer dataBuf)
{
    synchronized(dataBuf){
        dataBuf.rewind();

        dataBuf.get(name, 0, DataConstants.Cover_NameLength);
        dataBuf.get(id, 0, DataConstants.Cover_IdLength);
        dataBuf.get(sex, 0, DataConstants.Cover_SexLength);
        dataBuf.get(age, 0, DataConstants.Cover_AgeLength);
    }
}

OR

Create a new ByteBuffer for each.

public void populate(ByteBuffer dataBuf)
{
    ByteBuffer myDataBuf = dataBuf.asReadOnlyBuffer();
    myDataBuf.get(name, 0, DataConstants.Cover_NameLength);
    myDataBuf.get(id, 0, DataConstants.Cover_IdLength);
    myDataBuf.get(sex, 0, DataConstants.Cover_SexLength);
    myDataBuf.get(age, 0, DataConstants.Cover_AgeLength);
}

1 Comment

I tried the synchronized approach, it doesn't work in my case because there are other places the ByteBuffer is accessed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.