Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions java/fory-core/src/main/java/org/apache/fory/Fory.java
Original file line number Diff line number Diff line change
Expand Up @@ -1712,6 +1712,10 @@ public boolean isCompatible() {
return config.getCompatibleMode() == CompatibleMode.COMPATIBLE;
}

public boolean isShareMeta() {
return shareMeta;
}

public boolean trackingRef() {
return refTracking;
}
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,7 @@ private Expression serializeGroup(
// `bean` will be replaced by `Reference` to cut-off expr dependency.
Expression fieldValue = getFieldValue(bean, d);
walkPath.add(d.getDeclaringClass() + d.getName());
boolean nullable = d.isNullable();
Expression fieldExpr =
serializeForNullable(fieldValue, buffer, d.getTypeRef(), nullable);
Expression fieldExpr = serializeField(fieldValue, buffer, d);
walkPath.removeLast();
groupExpressions.add(fieldExpr);
}
Expand Down Expand Up @@ -555,17 +553,15 @@ protected Expression deserializeGroup(
for (Descriptor d : group) {
ExpressionVisitor.ExprHolder exprHolder = ExpressionVisitor.ExprHolder.of("bean", bean);
walkPath.add(d.getDeclaringClass() + d.getName());
boolean nullable = d.isNullable();
Expression action =
deserializeForNullable(
deserializeField(
buffer,
d.getTypeRef(),
d,
// `bean` will be replaced by `Reference` to cut-off expr
// dependency.
expr ->
setFieldValue(
exprHolder.get("bean"), d, tryInlineCast(expr, d.getTypeRef())),
nullable);
exprHolder.get("bean"), d, tryInlineCast(expr, d.getTypeRef())));
walkPath.removeLast();
groupExpressions.add(action);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
import org.apache.fory.serializer.CompatibleSerializer;
import org.apache.fory.serializer.EnumSerializer;
import org.apache.fory.serializer.ExternalizableSerializer;
import org.apache.fory.serializer.FinalFieldReplaceResolveSerializer;
import org.apache.fory.serializer.ForyCopyableSerializer;
import org.apache.fory.serializer.JavaSerializer;
import org.apache.fory.serializer.JdkProxySerializer;
Expand Down Expand Up @@ -789,8 +790,8 @@ public void clearSerializer(Class<?> cls) {
}
}

/** Ass serializer for specified class. */
private void addSerializer(Class<?> type, Serializer<?> serializer) {
/** Add serializer for specified class. */
public void addSerializer(Class<?> type, Serializer<?> serializer) {
Preconditions.checkNotNull(serializer);
// 1. Try to get ClassInfo from `registeredId2ClassInfo` and
// `classInfoMap` or create a new `ClassInfo`.
Expand All @@ -801,7 +802,8 @@ private void addSerializer(Class<?> type, Serializer<?> serializer) {
if (registered) {
classInfo = registeredId2ClassInfo[classId];
} else {
if (serializer instanceof ReplaceResolveSerializer) {
if (serializer instanceof ReplaceResolveSerializer
&& !(serializer instanceof FinalFieldReplaceResolveSerializer)) {
classId = REPLACE_STUB_ID;
} else {
classId = NO_CLASS_ID;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,7 @@ public <T> Serializer<T> getSerializer(Class<T> cls) {
return (Serializer) getClassInfo(cls).serializer;
}

@Override
public Serializer<?> getRawSerializer(Class<?> cls) {
return getClassInfo(cls).serializer;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,12 @@ private FinalTypeField(Fory fory, Descriptor d) {
classInfo = null;
} else {
classInfo = SerializationUtils.getClassInfo(fory, typeRef.getRawType());
if (!fory.isShareMeta()
&& !fory.isCompatible()
&& classInfo.getSerializer() instanceof ReplaceResolveSerializer) {
// overwrite replace resolve serializer for final field
classInfo.setSerializer(new FinalFieldReplaceResolveSerializer(fory, classInfo.getCls()));
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.fory.serializer;

import org.apache.fory.Fory;
import org.apache.fory.config.CompatibleMode;
import org.apache.fory.memory.MemoryBuffer;

/**
* Serializer for class which: - has jdk `writeReplace`/`readResolve` method defined, - is a final
* class. Main advantage of this serializer is that it does not write class name to the payload.
* NOTE: this serializer is used only with {@link CompatibleMode#SCHEMA_CONSISTENT} mode.
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public class FinalFieldReplaceResolveSerializer extends ReplaceResolveSerializer {

public FinalFieldReplaceResolveSerializer(Fory fory, Class type) {
// the serializer does not write class info
// and does not set itself for the provided class
// see checks in ReplaceResolveSerializer constructor
super(fory, type, true, false);
}

@Override
protected void writeObject(
MemoryBuffer buffer, Object value, MethodInfoCache jdkMethodInfoCache) {
jdkMethodInfoCache.objectSerializer.write(buffer, value);
}

@Override
protected Object readObject(MemoryBuffer buffer) {
MethodInfoCache jdkMethodInfoCache = getMethodInfoCache(type);
Object o = jdkMethodInfoCache.objectSerializer.read(buffer);
ReplaceResolveInfo replaceResolveInfo = jdkMethodInfoCache.info;
if (replaceResolveInfo.readResolveMethod == null) {
return o;
}
return replaceResolveInfo.readResolve(o);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,15 @@ public class ReplaceResolveSerializer extends Serializer {
*/
public static class ReplaceStub {}

private static final byte ORIGINAL = 0;
private static final byte REPLACED_NEW_TYPE = 1;
private static final byte REPLACED_SAME_TYPE = 2;
protected static final byte ORIGINAL = 0;
protected static final byte REPLACED_NEW_TYPE = 1;
protected static final byte REPLACED_SAME_TYPE = 2;

// Extract Method Info to cache for graalvm build time lambda generation and avoid
// generate function repeatedly too.
private static class ReplaceResolveInfo {
private final Method writeReplaceMethod;
private final Method readResolveMethod;
protected static class ReplaceResolveInfo {
protected final Method writeReplaceMethod;
protected final Method readResolveMethod;
private final Function writeReplaceFunc;
private final Function readResolveFunc;

Expand Down Expand Up @@ -162,10 +162,10 @@ protected ReplaceResolveInfo computeValue(Class<?> type) {
}
};

private static class MethodInfoCache {
private final ReplaceResolveInfo info;
protected static class MethodInfoCache {
protected final ReplaceResolveInfo info;

private Serializer objectSerializer;
protected Serializer objectSerializer;

public MethodInfoCache(ReplaceResolveInfo info) {
this.info = info;
Expand Down Expand Up @@ -210,26 +210,38 @@ private static Serializer createDataSerializer(
return serializer;
}

private final RefResolver refResolver;
private final ClassResolver classResolver;
private final MethodInfoCache jdkMethodInfoWriteCache;
private final ClassInfo writeClassInfo;
private final Map<Class<?>, MethodInfoCache> classClassInfoHolderMap = new HashMap<>();
protected final RefResolver refResolver;
protected final ClassResolver classResolver;
protected final MethodInfoCache jdkMethodInfoWriteCache;
protected final ClassInfo writeClassInfo;
protected final Map<Class<?>, MethodInfoCache> classClassInfoHolderMap = new HashMap<>();

public ReplaceResolveSerializer(Fory fory, Class type) {
this(fory, type, false, true);
}

public ReplaceResolveSerializer(
Fory fory, Class type, boolean isFinalField, boolean setSerializer) {
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);
if (setSerializer) {
// `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);
}
if (type != ReplaceStub.class) {
jdkMethodInfoWriteCache = newJDKMethodInfoCache(type, fory);
classClassInfoHolderMap.put(type, jdkMethodInfoWriteCache);
// FIXME new classinfo may miss serializer update in async compilation mode.
writeClassInfo = classResolver.newClassInfo(type, this, ClassResolver.NO_CLASS_ID);
if (isFinalField) {
writeClassInfo = null;
} else {
// FIXME new classinfo may miss serializer update in async compilation mode.
writeClassInfo = classResolver.newClassInfo(type, this, ClassResolver.NO_CLASS_ID);
}
} else {
jdkMethodInfoWriteCache = null;
writeClassInfo = null;
Expand Down Expand Up @@ -280,7 +292,8 @@ public void write(MemoryBuffer buffer, Object value) {
}
}

private void writeObject(MemoryBuffer buffer, Object value, MethodInfoCache jdkMethodInfoCache) {
protected void writeObject(
MemoryBuffer buffer, Object value, MethodInfoCache jdkMethodInfoCache) {
classResolver.writeClassInternal(buffer, writeClassInfo);
jdkMethodInfoCache.objectSerializer.write(buffer, value);
}
Expand Down Expand Up @@ -319,7 +332,7 @@ public Object read(MemoryBuffer buffer) {
}
}

private Object readObject(MemoryBuffer buffer) {
protected Object readObject(MemoryBuffer buffer) {
Class cls = classResolver.readClassInternal(buffer);
MethodInfoCache jdkMethodInfoCache = getMethodInfoCache(cls);
Object o = jdkMethodInfoCache.objectSerializer.read(buffer);
Expand Down Expand Up @@ -350,7 +363,7 @@ public Object copy(Object originObj) {
return newObj;
}

private MethodInfoCache getMethodInfoCache(Class<?> cls) {
protected MethodInfoCache getMethodInfoCache(Class<?> cls) {
MethodInfoCache jdkMethodInfoCache = classClassInfoHolderMap.get(cls);
if (jdkMethodInfoCache == null) {
jdkMethodInfoCache = newJDKMethodInfoCache(cls, fory);
Expand Down
Loading
Loading