-
Notifications
You must be signed in to change notification settings - Fork 258
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore(java): Disallow writing meta classdef when obj is null #1686
Conversation
ClassInfo classInfo = classResolver.getOrUpdateClassInfo(obj.getClass()); | ||
classResolver.writeClass(buffer, classInfo); | ||
writeData(buffer, classInfo, obj); | ||
} | ||
if (shareMeta) { | ||
if (shareMeta && !isNull) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The deserialization will still read class meta, but the offset will be -1, then the read will fail. Could you add an UT for such case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
CI failure is not related to the current changes, fix it in #1691.
2f45408
to
8f4f13a
Compare
The code looks good to me. But do we really to optimize this? When value is null, the ClassDef list is empty, only one byte are written in such cases |
There will be two more write overheads (putInt32, writeVarUint32Small7), which is also a small problem I found while reading the code. If there is no negative impact, I think it can be merged. |
Hi @chaokunyang , could you reply to this PR? |
buffer.putInt32(startOffset, buffer.writerIndex()); | ||
classResolver.writeClassDefs(buffer); | ||
} | ||
} | ||
|
||
private void xserializeInternal(MemoryBuffer buffer, Object obj) { | ||
int startOffset = buffer.writerIndex(); | ||
buffer.writeInt32(-1); // preserve 4-byte for nativeObjects start offsets. | ||
buffer.writeInt32( | ||
Constants.INVALID_OFFSITE); // preserve 4-byte for nativeObjects start offsets. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an internal, could we keep it inside this class
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about checking meta list size and remove this part of code from class resolver into Fury |
I don't think it's necessary. Reading Why would we do this? Just to move |
When object is not null, but the type is internal types such pritimitive type, string or ArrayList/HashMap, the meta list will be empty too, which can be optimized as the null value |
Not only internal types, but also the meta list of registered classes(
private void write(MemoryBuffer buffer, Object obj) {
int startOffset = buffer.writerIndex();
boolean shareMeta = config.isMetaShareEnabled();
if (shareMeta) {
buffer.writeInt32(INVALID_OFFSITE); // preserve 4-byte for nativeObjects start offsets.
}
// reduce caller stack
boolean isNull = refResolver.writeRefOrNull(buffer, obj);
if (!isNull) {
ClassInfo classInfo = classResolver.getOrUpdateClassInfo(obj.getClass());
classResolver.writeClass(buffer, classInfo);
writeData(buffer, classInfo, obj);
}
// **Just determine the meta list size.**
if (shareMeta && !isNull && !serializationContext.getMetaContext().writingClassDefs.isEmpty()) {
buffer.putInt32(startOffset, buffer.writerIndex());
classResolver.writeClassDefs(buffer);
}
} Is it possible to determine the meta list size at the end? |
@chaokunyang Any other suggestions? If so, please let me know. |
For the meta list of registered classes(classInfo.classId != NO_CLASS_ID), we still need to write meta, this needs being done before we set scopde meta share as the default compatible mode |
We can check meta size before writing meta |
I mean if the current class has been registered, the information of the current class will not be written back to meta. public void writeClass(MemoryBuffer buffer, ClassInfo classInfo) {
if (classInfo.classId == NO_CLASS_ID) { // no class id provided.
// use classname
if (metaContextShareEnabled) {
buffer.writeByte(USE_CLASS_VALUE_FLAG);
// FIXME(chaokunyang) Register class but not register serializer can't be used with
// meta share mode, because no class def are sent to peer.
writeClassWithMetaShare(buffer, classInfo);
} else {
// if it's null, it's a bug.
assert classInfo.packageNameBytes != null;
metaStringResolver.writeMetaStringBytesWithFlag(buffer, classInfo.packageNameBytes);
assert classInfo.classNameBytes != null;
metaStringResolver.writeMetaStringBytes(buffer, classInfo.classNameBytes);
}
} else {
// use classId
buffer.writeVarUint32(classInfo.classId << 1);
}
} |
Done |
package org.apache.fury.type; | ||
|
||
public class Constants { | ||
public static final int INVALID_OFFSITE = -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I perfer not expose this variable. It's an internal implementation, we'd better keep it private
Signed-off-by: LiangliangSui <[email protected]>
Signed-off-by: LiangliangSui <[email protected]>
Signed-off-by: LiangliangSui <[email protected]>
Hi @chaokunyang , could you please take a look? |
Signed-off-by: LiangliangSui <[email protected]>
The above comments has been completed, please help review again. |
@chaokunyang please help review this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
What does this PR do?
When obj is null, if shareMeta is enabled, no need to write meta classdef
Related issues
Does this PR introduce any user-facing change?
Benchmark