Skip to content

Commit

Permalink
[Java] Support jit for non public classes (#719)
Browse files Browse the repository at this point in the history
* support jit for non pblic classes

* make guava serializers jit async

* lint code

* add private bean jit tests and package level bean test

* add private bean jit tests and package level bean test
  • Loading branch information
chaokunyang authored Jul 21, 2023
1 parent bc45b20 commit 6b02412
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 36 deletions.
2 changes: 1 addition & 1 deletion java/fury-core/src/main/java/io/fury/Fury.java
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ private Fury(FuryBuilder builder, ClassLoader classLoader) {
} else {
this.refResolver = new NoRefResolver();
}
jitContext = new JITContext(this);
enumStringResolver = new EnumStringResolver();
classResolver = new ClassResolver(this);
classResolver.initialize();
Expand All @@ -132,7 +133,6 @@ private Fury(FuryBuilder builder, ClassLoader classLoader) {
nativeObjects = new ArrayList<>();
generics = new Generics(this);
stringSerializer = new StringSerializer(this);
jitContext = new JITContext(this);
LOG.info("Created new fury {}", this);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ protected Expression getFieldValue(Expression inputBeanExpr, Descriptor descript
Modifier.isPublic(getRawType(fieldType).getModifiers()),
"Field type should be public for codegen-based access");
String fieldName = descriptor.getName();
if (duplicatedFields.contains(fieldName)) {
if (duplicatedFields.contains(fieldName) || !Modifier.isPublic(beanClass.getModifiers())) {
return unsafeAccessField(inputBeanExpr, beanClass, descriptor);
}
// public field or non-private non-java field access field directly.
Expand Down Expand Up @@ -200,7 +200,7 @@ protected Expression setFieldValue(Expression bean, Descriptor d, Expression val
if (value instanceof Inlineable) {
((Inlineable) value).inline();
}
if (duplicatedFields.contains(fieldName)) {
if (duplicatedFields.contains(fieldName) || !Modifier.isPublic(beanClass.getModifiers())) {
return unsafeSetField(bean, d, value);
}
if (!Modifier.isFinal(d.getModifiers()) && Modifier.isPublic(d.getModifiers())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@

package io.fury.serializer;

import static io.fury.type.TypeUtils.getRawType;
import static io.fury.util.Utils.checkArgument;

import com.google.common.reflect.TypeToken;
import io.fury.Fury;
import io.fury.builder.CodecUtils;
import io.fury.builder.Generated;
Expand All @@ -37,19 +35,8 @@
public final class CodegenSerializer {

public static boolean supportCodegenForJavaSerialization(Class<?> cls) {
return isJavaPojo(TypeToken.of(cls));
}

private static boolean isJavaPojo(TypeToken<?> type) {
Class<?> rawType = getRawType(type);
// since we need to access class in generated code in our package, the class must be public.
// TODO support default access-level class jit.
if (Modifier.isPublic(rawType.getModifiers())) {
// bean class can be static nested class, but can't be a non-static inner class
return rawType.getEnclosingClass() == null || Modifier.isStatic(rawType.getModifiers());
} else {
return false;
}
// bean class can be static nested class, but can't be a non-static inner class
return cls.getEnclosingClass() == null || Modifier.isStatic(cls.getModifiers());
}

@SuppressWarnings("unchecked")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,23 +44,31 @@ public class GuavaSerializers {

abstract static class GuavaCollectionSerializer<T extends Collection>
extends CollectionSerializer<T> {
private final ReplaceResolveSerializer serializer;
private ReplaceResolveSerializer serializer;

public GuavaCollectionSerializer(Fury fury, Class<T> cls) {
super(fury, cls, false, false);
fury.getClassResolver().setSerializer(cls, this);
serializer = new ReplaceResolveSerializer(fury, cls);
}

protected ReplaceResolveSerializer getOrCreateSerializer() {
// reduce cost of fury creation, ReplaceResolveSerializer will jit-generate serializer.
ReplaceResolveSerializer serializer = this.serializer;
if (serializer == null) {
this.serializer = serializer = new ReplaceResolveSerializer(fury, type);
}
return serializer;
}

@SuppressWarnings("unchecked")
@Override
public T read(MemoryBuffer buffer) {
return (T) serializer.read(buffer);
return (T) getOrCreateSerializer().read(buffer);
}

@Override
public void write(MemoryBuffer buffer, T value) {
serializer.write(buffer, value);
getOrCreateSerializer().write(buffer, value);
}

@Override
Expand Down Expand Up @@ -122,23 +130,31 @@ protected T xnewInstance(Collection collection) {
}

abstract static class GuavaMapSerializer<T extends Map> extends MapSerializer<T> {
private final ReplaceResolveSerializer serializer;
private ReplaceResolveSerializer serializer;

public GuavaMapSerializer(Fury fury, Class<T> cls) {
super(fury, cls, false, false);
fury.getClassResolver().setSerializer(cls, this);
serializer = new ReplaceResolveSerializer(fury, cls);
}

protected ReplaceResolveSerializer getOrCreateSerializer() {
// reduce cost of fury creation, ReplaceResolveSerializer will jit-generate serializer.
ReplaceResolveSerializer serializer = this.serializer;
if (serializer == null) {
this.serializer = serializer = new ReplaceResolveSerializer(fury, type);
}
return serializer;
}

@SuppressWarnings("unchecked")
@Override
public T read(MemoryBuffer buffer) {
return (T) serializer.read(buffer);
return (T) getOrCreateSerializer().read(buffer);
}

@Override
public void write(MemoryBuffer buffer, T value) {
serializer.write(buffer, value);
getOrCreateSerializer().write(buffer, value);
}

@Override
Expand Down
53 changes: 43 additions & 10 deletions java/fury-core/src/test/java/io/fury/FuryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@

public class FuryTest extends FuryTestBase {
@DataProvider(name = "languageConfig")
public static Object[] languageConfig() {
return new Object[] {Language.JAVA, Language.PYTHON};
public static Object[][] languageConfig() {
return new Object[][] {{Language.JAVA}, {Language.PYTHON}};
}

@Test(dataProvider = "crossLanguageReferenceTrackingConfig")
Expand Down Expand Up @@ -275,22 +275,55 @@ private static class Inner {
}
}

@Test(dataProvider = "referenceTrackingConfig")
public void testSerializePrivateBean(boolean referenceTracking) {
@Test
public void testSerializePrivateBean() {
Fury fury =
Fury.builder()
.withLanguage(Language.JAVA)
.withRefTracking(referenceTracking)
.disableSecureMode()
.build();
Fury.builder().withLanguage(Language.JAVA).withCodegen(false).disableSecureMode().build();
Outer outer = new Outer();
outer.inner = new Outer.Inner();
fury.deserialize(fury.serialize(outer));
assertTrue(fury.getClassResolver().getSerializer(Outer.class) instanceof Generated);
assertTrue(fury.getClassResolver().getSerializer(Outer.class) instanceof ObjectSerializer);
assertTrue(
fury.getClassResolver().getSerializer(Outer.Inner.class) instanceof ObjectSerializer);
}

@Test
public void testSerializePrivateBeanJIT() {
Fury fury =
Fury.builder().withLanguage(Language.JAVA).withCodegen(true).disableSecureMode().build();
Outer outer = new Outer();
outer.inner = new Outer.Inner();
fury.deserialize(fury.serialize(outer));
assertTrue(fury.getClassResolver().getSerializer(Outer.class) instanceof Generated);
assertTrue(fury.getClassResolver().getSerializer(Outer.Inner.class) instanceof Generated);
}

@Data
public static class PackageLevelBean {
public long f1;
private long f2;
}

@Test
public void testSerializePackageLevelBean() {
Fury fury =
Fury.builder().withLanguage(Language.JAVA).withCodegen(false).disableSecureMode().build();
PackageLevelBean o = new PackageLevelBean();
o.f1 = 10;
o.f2 = 1;
serDeCheckSerializer(fury, o, "Object");
}

@Test
public void testSerializePackageLevelBeanJIT() {
Fury fury =
Fury.builder().withLanguage(Language.JAVA).withCodegen(true).disableSecureMode().build();
PackageLevelBean o = new PackageLevelBean();
o.f1 = 10;
o.f2 = 1;
serDeCheckSerializer(fury, o, "PackageLevelBean");
}

static class B {
int f1;
}
Expand Down

0 comments on commit 6b02412

Please sign in to comment.