From 01f8ae3f4d20d44a1e52cf36d23044886905ed0c Mon Sep 17 00:00:00 2001 From: chaokunyang Date: Sun, 3 Nov 2024 23:19:40 +0800 Subject: [PATCH 1/2] support scala native image build --- .../java/org/apache/fury/type/ScalaTypes.java | 61 +++++++++++++------ .../fury-core/native-image.properties | 35 +++++++++++ 2 files changed, 77 insertions(+), 19 deletions(-) create mode 100644 scala/src/main/resources/META-INF/native-image/org.apache.fury/fury-core/native-image.properties diff --git a/java/fury-core/src/main/java/org/apache/fury/type/ScalaTypes.java b/java/fury-core/src/main/java/org/apache/fury/type/ScalaTypes.java index 485776a828..a76c5f00e9 100644 --- a/java/fury-core/src/main/java/org/apache/fury/type/ScalaTypes.java +++ b/java/fury-core/src/main/java/org/apache/fury/type/ScalaTypes.java @@ -28,41 +28,64 @@ /** Scala types utils using reflection without dependency on scala library. */ @SuppressWarnings({"unchecked", "rawtypes"}) public class ScalaTypes { - private static final Class SCALA_MAP_TYPE; - private static final Class SCALA_SEQ_TYPE; - private static final Class SCALA_ITERABLE_TYPE; - private static final Class SCALA_ITERATOR_TYPE; - private static final java.lang.reflect.Type SCALA_ITERATOR_RETURN_TYPE; - private static final java.lang.reflect.Type SCALA_NEXT_RETURN_TYPE; + private static volatile Class SCALA_MAP_TYPE; + private static volatile Class SCALA_SEQ_TYPE; + private static volatile Class SCALA_ITERABLE_TYPE; + private static volatile java.lang.reflect.Type SCALA_ITERATOR_RETURN_TYPE; + private static volatile java.lang.reflect.Type SCALA_NEXT_RETURN_TYPE; - static { - try { - SCALA_ITERABLE_TYPE = ReflectionUtils.loadClass("scala.collection.Iterable"); - SCALA_ITERATOR_TYPE = ReflectionUtils.loadClass("scala.collection.Iterator"); + public static Class getScalaMapType() { + if (SCALA_MAP_TYPE == null) { + // load scala classes dynamically to make graalvm native build work + // see https://github.com/quarkiverse/quarkus-fury/issues/7 SCALA_MAP_TYPE = ReflectionUtils.loadClass("scala.collection.Map"); - SCALA_SEQ_TYPE = ReflectionUtils.loadClass("scala.collection.Seq"); - SCALA_ITERATOR_RETURN_TYPE = SCALA_ITERABLE_TYPE.getMethod("iterator").getGenericReturnType(); - SCALA_NEXT_RETURN_TYPE = SCALA_ITERATOR_TYPE.getMethod("next").getGenericReturnType(); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); } - } - - public static Class getScalaMapType() { return SCALA_MAP_TYPE; } public static Class getScalaSeqType() { + if (SCALA_SEQ_TYPE == null) { + SCALA_SEQ_TYPE = ReflectionUtils.loadClass("scala.collection.Seq"); + } return SCALA_SEQ_TYPE; } public static Class getScalaIterableType() { + if (SCALA_ITERABLE_TYPE == null) { + SCALA_ITERABLE_TYPE = ReflectionUtils.loadClass("scala.collection.Iterable"); + } return SCALA_ITERABLE_TYPE; } public static TypeRef getElementType(TypeRef typeRef) { TypeRef supertype = typeRef.getSupertype(getScalaIterableType()); - return supertype.resolveType(SCALA_ITERATOR_RETURN_TYPE).resolveType(SCALA_NEXT_RETURN_TYPE); + return supertype + .resolveType(getScalaIteratorReturnType()) + .resolveType(getScalaNextReturnType()); + } + + private static Type getScalaIteratorReturnType() { + if (SCALA_ITERATOR_RETURN_TYPE == null) { + try { + SCALA_ITERATOR_RETURN_TYPE = + getScalaIterableType().getMethod("iterator").getGenericReturnType(); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + return SCALA_ITERATOR_RETURN_TYPE; + } + + private static Type getScalaNextReturnType() { + if (SCALA_NEXT_RETURN_TYPE == null) { + Class SCALA_ITERATOR_TYPE = ReflectionUtils.loadClass("scala.collection.Iterator"); + try { + SCALA_NEXT_RETURN_TYPE = SCALA_ITERATOR_TYPE.getMethod("next").getGenericReturnType(); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + return SCALA_NEXT_RETURN_TYPE; } /** Returns key/value type of scala map. */ diff --git a/scala/src/main/resources/META-INF/native-image/org.apache.fury/fury-core/native-image.properties b/scala/src/main/resources/META-INF/native-image/org.apache.fury/fury-core/native-image.properties new file mode 100644 index 0000000000..bdc7207e71 --- /dev/null +++ b/scala/src/main/resources/META-INF/native-image/org.apache.fury/fury-core/native-image.properties @@ -0,0 +1,35 @@ +# 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. + +# https://www.graalvm.org/latest/reference-manual/native-image/dynamic-features/Reflection/#unsafe-accesses : +# The unsafe offset get on build time may be different from runtime +Args=--initialize-at-build-time=org.apache.fury.type.ScalaTypes,\ + org.apache.fury.type.Seq,\ + org.apache.fury.type.Map,\ + org.apache.fury.type.Iterable,\ + scala.collection.Iterator,\ + org.apache.fury.serializer.scala.ScalaDispatcher,\ + org.apache.fury.serializer.scala.AbstractScalaCollectionSerializer,\ + org.apache.fury.serializer.scala.AbstractScalaMapSerializer,\ + org.apache.fury.serializer.scala.ScalaSortedMapSerializer,\ + org.apache.fury.serializer.scala.ScalaMapSerializer,\ + org.apache.fury.serializer.scala.ScalaSortedSetSerializer,\ + org.apache.fury.serializer.scala.ScalaSeqSerializer,\ + org.apache.fury.serializer.scala.ScalaCollectionSerializer,\ + org.apache.fury.serializer.scala.RangeSerializer,\ + org.apache.fury.serializer.scala.RangeUtils$,\ + org.apache.fury.serializer.scala.NumericRangeSerializer From ecb880498181021bc4c1cc191634eac0fcd0f62b Mon Sep 17 00:00:00 2001 From: chaokunyang Date: Sun, 3 Nov 2024 23:27:35 +0800 Subject: [PATCH 2/2] lint code --- .../src/main/java/org/apache/fury/type/ScalaTypes.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/fury-core/src/main/java/org/apache/fury/type/ScalaTypes.java b/java/fury-core/src/main/java/org/apache/fury/type/ScalaTypes.java index a76c5f00e9..31d439067f 100644 --- a/java/fury-core/src/main/java/org/apache/fury/type/ScalaTypes.java +++ b/java/fury-core/src/main/java/org/apache/fury/type/ScalaTypes.java @@ -78,9 +78,9 @@ private static Type getScalaIteratorReturnType() { private static Type getScalaNextReturnType() { if (SCALA_NEXT_RETURN_TYPE == null) { - Class SCALA_ITERATOR_TYPE = ReflectionUtils.loadClass("scala.collection.Iterator"); + Class scalaIteratorType = ReflectionUtils.loadClass("scala.collection.Iterator"); try { - SCALA_NEXT_RETURN_TYPE = SCALA_ITERATOR_TYPE.getMethod("next").getGenericReturnType(); + SCALA_NEXT_RETURN_TYPE = scalaIteratorType.getMethod("next").getGenericReturnType(); } catch (NoSuchMethodException e) { throw new RuntimeException(e); }