Skip to content

Conversation

@mchernyakov
Copy link
Contributor

Why?

Based on the discussion #2786.
We can optimize the payload in cases where we have final fields in some Object.

re-created, closed PR #2904

What does this PR do?

Introduce FinalFieldReplaceResolver which does not write the classname into the payload.

Related issues

Does this PR introduce any user-facing change?

  • Does this PR introduce any public API change?
  • Does this PR introduce any binary protocol compatibility change?

Benchmark

@mchernyakov
Copy link
Contributor Author

@chaokunyang re-created my PR, addressed your comments in slack, please check

@Internal
@CodegenInvoke
@Override
public Serializer<?> getRawSerializerFinalField(Class<?> cls) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only used in codegen, how baout using Invoke expression to create serializer directly?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If so, most of changes in this file can be removed

Copy link
Contributor Author

@mchernyakov mchernyakov Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chaokunyang which one is more preferable

// BaseObjectCodecBuilder
....
  private static final TypeRef<?> FINAL_FIELD_SERIALIZER_TYPE =
      TypeRef.of(FinalFieldReplaceResolveSerializer.class);
...
// in private Expression getOrCreateSerializer(Class<?> cls, boolean isField)
        newSerializerExpr =
            new Expression.NewInstance(FINAL_FIELD_SERIALIZER_TYPE, foryRef, fieldTypeExpr);

or

// BaseObjectCodecBuilder
...
  private static final TypeRef<?> FINAL_FIELD_SERIALIZER_TYPE =
      TypeRef.of(FinalFieldReplaceResolveSerializer.class);
...
// in private Expression getOrCreateSerializer(Class<?> cls, boolean isField)
        newSerializerExpr =
            new Expression.StaticInvoke(
                FinalFieldReplaceResolveSerializer.class,
                "createSerializer",
                FINAL_FIELD_SERIALIZER_TYPE,
                foryRef,
                fieldTypeExpr);
...
// FinalFieldReplaceResolveSerializer
...
  @CodegenInvoke
  public static FinalFieldReplaceResolveSerializer createSerializer(Fory fory, Class type) {
    return new FinalFieldReplaceResolveSerializer(fory, type);
  }
...

?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer first one

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done cf8b80d

public class FinalFieldReplaceResolveSerializer extends ReplaceResolveSerializer {

public FinalFieldReplaceResolveSerializer(Fory fory, Class type) {
super(fory, type, true);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super class will invoke :

  public ReplaceResolveSerializer(Fory fory, Class type) {
    super(fory, type);
    refResolver = fory.getRefResolver();
    classResolver = fory.getClassResolver();
    // `setSerializer` before `newJDKMethodInfoCache` since it query classinfo from `classResolver`,
    // which create serializer in turn.
    // ReplaceResolveSerializer is used as data serializer for ImmutableList/Map,
    // which serializer is already set.
    classResolver.setSerializerIfAbsent(type, this);

classResolver.setSerializerIfAbsent(type, this); may set wrong serializer, could we add another protected contrcutore in parent class to pass setSerializer param and pass false here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chaokunyang
Copy link
Collaborator

Hi @mchernyakov , sorry for review late. I've reviewed this PR, most of parts are fine, I left some minor comments. We can merge it after those are resolved.

And since it changes binary compatibility, we will include this PR in 0.14.0 instead 0.13.2


/**
* Serializer for class which 1) has jdk `writeReplace`/`readResolve` method defined, 2) is a final
* field of a class. //TODO do we ned to write the flag REPLACED_NEW_TYPE/REPLACED_SAME_TYPE even
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

waht does this TODO means?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we also document that this serializer only works for consist mode, and add checks in FinalFieldReplaceResolveSerializer constructor.

Copy link
Contributor Author

@mchernyakov mchernyakov Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added in 446cc65 and removed the TODO

Copy link
Collaborator

@chaokunyang chaokunyang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@chaokunyang chaokunyang merged commit ae1a7e0 into apache:main Dec 2, 2025
55 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants