diff --git a/.github/workflows/serverless_runtime_release.yml b/.github/workflows/serverless_runtime_release.yml index a0c5dd471..a6faa317c 100644 --- a/.github/workflows/serverless_runtime_release.yml +++ b/.github/workflows/serverless_runtime_release.yml @@ -40,7 +40,7 @@ jobs: gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase - name: Build with Maven - run: mvn --batch-mode deploy -DskipTests -Prelease + run: mvn --batch-mode deploy -DskipTests -Prelease,8-release working-directory: sofa-serverless-runtime env: MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} @@ -63,9 +63,9 @@ jobs: gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase - name: Build with Maven - run: mvn --batch-mode deploy -DskipTests -Prelease + run: mvn --batch-mode deploy -DskipTests -Prelease,17-release working-directory: sofa-serverless-runtime env: MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} - MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} + MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} \ No newline at end of file diff --git a/.github/workflows/serverless_runtime_snapshot.yml b/.github/workflows/serverless_runtime_snapshot.yml index 0e62cbc09..6c5110a6e 100644 --- a/.github/workflows/serverless_runtime_snapshot.yml +++ b/.github/workflows/serverless_runtime_snapshot.yml @@ -25,7 +25,7 @@ jobs: gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase - name: Build with Maven - run: mvn --batch-mode deploy -DskipTests -Psnapshot + run: mvn --batch-mode deploy -DskipTests -Psnapshot,8-snapshot working-directory: sofa-serverless-runtime env: MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} @@ -48,9 +48,9 @@ jobs: gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase - name: Build with Maven - run: mvn --batch-mode deploy -DskipTests -Psnapshot + run: mvn --batch-mode deploy -DskipTests -Psnapshot,17-snapshot working-directory: sofa-serverless-runtime env: MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} - MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} + MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} \ No newline at end of file diff --git a/samples/springboot3-samples/db/mybatis/README.md b/samples/springboot3-samples/db/mybatis/README.md index 311750b43..2e54734d2 100644 --- a/samples/springboot3-samples/db/mybatis/README.md +++ b/samples/springboot3-samples/db/mybatis/README.md @@ -11,7 +11,7 @@ base 为普通 springboot 改造成的基座,改造内容为在 pom 里增加 com.alipay.sofa.serverless sofa-serverless-base-starter - 0.5.2-jdk17-SNAPSHOT + 0.5.3-jdk17 diff --git a/samples/springboot3-samples/db/mybatis/base/pom.xml b/samples/springboot3-samples/db/mybatis/base/pom.xml index d3fc8431e..9a273423c 100644 --- a/samples/springboot3-samples/db/mybatis/base/pom.xml +++ b/samples/springboot3-samples/db/mybatis/base/pom.xml @@ -68,7 +68,7 @@ com.alipay.sofa.serverless sofa-serverless-base-starter - 0.5.2-jdk17-SNAPSHOT + 0.5.3-jdk17 diff --git a/samples/springboot3-samples/logging/README.md b/samples/springboot3-samples/logging/README.md index b4fd34484..69176dfc1 100644 --- a/samples/springboot3-samples/logging/README.md +++ b/samples/springboot3-samples/logging/README.md @@ -13,7 +13,7 @@ base 为普通 springboot 改造成的基座,改造内容为在 pom 里增加 com.alipay.sofa.serverless sofa-serverless-base-starter - 0.5.2-jdk17-SNAPSHOT + 0.5.3-jdk17 diff --git a/samples/springboot3-samples/logging/log4j2/base/pom.xml b/samples/springboot3-samples/logging/log4j2/base/pom.xml index ce604aecf..d336c53ef 100644 --- a/samples/springboot3-samples/logging/log4j2/base/pom.xml +++ b/samples/springboot3-samples/logging/log4j2/base/pom.xml @@ -31,7 +31,7 @@ com.alipay.sofa.serverless sofa-serverless-base-starter - 0.5.2-jdk17-SNAPSHOT + 0.5.3-jdk17 diff --git a/samples/springboot3-samples/msg/kafka/README.md b/samples/springboot3-samples/msg/kafka/README.md index 6c78d84d9..eab9a5c6e 100644 --- a/samples/springboot3-samples/msg/kafka/README.md +++ b/samples/springboot3-samples/msg/kafka/README.md @@ -11,7 +11,7 @@ base 为普通 springboot 改造成的基座,改造内容为在 pom 里增加 com.alipay.sofa.serverless sofa-serverless-base-starter - 0.5.2-jdk17-SNAPSHOT + 0.5.3-jdk17 diff --git a/samples/springboot3-samples/msg/kafka/base/pom.xml b/samples/springboot3-samples/msg/kafka/base/pom.xml index 91753aaf3..920852b4b 100644 --- a/samples/springboot3-samples/msg/kafka/base/pom.xml +++ b/samples/springboot3-samples/msg/kafka/base/pom.xml @@ -47,7 +47,7 @@ com.alipay.sofa.serverless sofa-serverless-base-starter - 0.5.2-jdk17-SNAPSHOT + 0.5.3-jdk17 diff --git a/samples/springboot3-samples/web/tomcat/README.md b/samples/springboot3-samples/web/tomcat/README.md index edb24b513..ddf5df5e4 100644 --- a/samples/springboot3-samples/web/tomcat/README.md +++ b/samples/springboot3-samples/web/tomcat/README.md @@ -13,7 +13,7 @@ base 为普通 springboot 改造成的基座,改造内容为在 pom 里增加 com.alipay.sofa.serverless sofa-serverless-base-starter - 0.5.2-jdk17-SNAPSHOT + 0.5.3-jdk17 diff --git a/samples/springboot3-samples/web/tomcat/base/pom.xml b/samples/springboot3-samples/web/tomcat/base/pom.xml index 4f0d4dc60..8ad0a71a4 100644 --- a/samples/springboot3-samples/web/tomcat/base/pom.xml +++ b/samples/springboot3-samples/web/tomcat/base/pom.xml @@ -36,7 +36,7 @@ com.alipay.sofa.serverless sofa-serverless-base-starter - 0.5.2-jdk17-SNAPSHOT + 0.5.3-jdk17 diff --git a/sofa-serverless-runtime/pom.xml b/sofa-serverless-runtime/pom.xml index 6fc8dfb73..7da72ace4 100644 --- a/sofa-serverless-runtime/pom.xml +++ b/sofa-serverless-runtime/pom.xml @@ -11,13 +11,10 @@ 2.2.4 - 2.2.4-SNAPSHOT - 0.5.3-SNAPSHOT + 0.5.3 UTF-8 UTF-8 1.8 @@ -35,7 +32,7 @@ 1.5.0 6.4.5 3.12.0 - 4.0 + 5.1.0 4.1.42.Final 1.2.9 1.18.22 @@ -156,9 +153,24 @@ com.alipay.sofa - sofa-ark-springboot-starter + sofa-ark-support-starter + ${sofa.ark.version} + + + com.alipay.sofa + sofa-ark-compatible-springboot1 + ${sofa.ark.version} + + + com.alipay.sofa + sofa-ark-compatible-springboot2 ${sofa.ark.version} + + com.alipay.sofa + sofa-ark-springboot-starter + ${sofa.ark.starter.version} + org.springframework.boot @@ -200,7 +212,7 @@ com.google.inject.extensions guice-multibindings - ${guice.version} + 4.2.3 @@ -480,25 +492,71 @@ + - jakarta-snapshot + 17-snapshot ${revision.default}-jdk17-SNAPSHOT - ${sofa.ark.version.base}-jdk17-SNAPSHOT - ${sofa.ark.version.base}-jdk17-jakarta-SNAPSHOT + ${sofa.ark.version.base}-jdk17 + ${sofa.ark.version.base}-jdk17-jakarta + + + + + 17-release + + ${revision.default}-jdk17 + ${sofa.ark.version.base}-jdk17 + ${sofa.ark.version.base}-jdk17-jakarta - - 17 - + - release + 8-snapshot + + ${revision.default}-SNAPSHOT + ${sofa.ark.version.base} + ${sofa.ark.version.base} + + + + + + 8-release ${revision.default} - ${sofa.ark.version.default} - ${sofa.ark.version.default} + ${sofa.ark.version.base} + ${sofa.ark.version.base} + + + + release @@ -560,15 +618,19 @@ https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + true + + maven-snapshot + https://oss.sonatype.org/content/repositories/snapshots + + snapshot - - ${revision.default} - ${sofa.ark.version.default} - ${sofa.ark.version.default} - @@ -609,11 +671,25 @@ ossrh https://oss.sonatype.org/content/repositories/snapshots + + - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + true + + maven-snapshot + https://oss.sonatype.org/content/repositories/snapshots - + + + + + true + + maven-snapshot + https://oss.sonatype.org/content/repositories/snapshots + + @@ -623,8 +699,8 @@ ${revision.default} - ${sofa.ark.version.default} - ${sofa.ark.version.default} + ${sofa.ark.version.base} + ${sofa.ark.version.base} diff --git a/sofa-serverless-runtime/sofa-serverless-base-starter/pom.xml b/sofa-serverless-runtime/sofa-serverless-base-starter/pom.xml index 09c4ff473..0a75bf765 100644 --- a/sofa-serverless-runtime/sofa-serverless-base-starter/pom.xml +++ b/sofa-serverless-runtime/sofa-serverless-base-starter/pom.xml @@ -21,7 +21,6 @@ com.alipay.sofa sofa-ark-springboot-starter - ${sofa.ark.starter.version} diff --git a/sofa-serverless-runtime/sofa-serverless-common/src/main/java/com/alipay/sofa/serverless/common/util/LoaderUtil.java b/sofa-serverless-runtime/sofa-serverless-common/src/main/java/com/alipay/sofa/serverless/common/util/LoaderUtil.java new file mode 100644 index 000000000..9d355425f --- /dev/null +++ b/sofa-serverless-runtime/sofa-serverless-common/src/main/java/com/alipay/sofa/serverless/common/util/LoaderUtil.java @@ -0,0 +1,62 @@ +/* + * 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 com.alipay.sofa.serverless.common.util; + +/** + * Consider this class private. Utility class for ClassLoaders. + * + * @see ClassLoader + * @see RuntimePermission + * @see Thread#getContextClassLoader() + * @see ClassLoader#getSystemClassLoader() + */ +public final class LoaderUtil { + private LoaderUtil() { + } + + /** + * Gets the current Thread ClassLoader. Returns the system ClassLoader if the TCCL is {@code null}. If the system + * ClassLoader is {@code null} as well, then the ClassLoader for this class is returned. If running with a + * {@link SecurityManager} that does not allow access to the Thread ClassLoader or system ClassLoader, then the + * ClassLoader for this class is returned. + * + * @return the current ThreadContextClassLoader. + */ + public static ClassLoader getThreadContextClassLoader() { + final ClassLoader cl = Thread.currentThread().getContextClassLoader(); + if (cl != null) { + return cl; + } + final ClassLoader ccl = LoaderUtil.class.getClassLoader(); + return ccl == null ? ClassLoader.getSystemClassLoader() : ccl; + } + + /** + * @param className The class name. + * @return the Class for the given name. + * @throws ClassNotFoundException if the specified class name could not be found + * @since 2.1 + */ + public static Class loadClass(final String className) throws ClassNotFoundException { + try { + return getThreadContextClassLoader().loadClass(className); + } catch (final Throwable ignored) { + return Class.forName(className); + } + } + +} \ No newline at end of file diff --git a/sofa-serverless-runtime/sofa-serverless-common/src/main/java/com/alipay/sofa/serverless/common/util/ReflectionUtils.java b/sofa-serverless-runtime/sofa-serverless-common/src/main/java/com/alipay/sofa/serverless/common/util/ReflectionUtils.java index 85ae75893..e34381f64 100644 --- a/sofa-serverless-runtime/sofa-serverless-common/src/main/java/com/alipay/sofa/serverless/common/util/ReflectionUtils.java +++ b/sofa-serverless-runtime/sofa-serverless-common/src/main/java/com/alipay/sofa/serverless/common/util/ReflectionUtils.java @@ -36,7 +36,59 @@ public class ReflectionUtils { } } - public static Class getCallerClass(int realFramesToSkip) { + public static StackTraceElement getEquivalentStackTraceElement(final int depth) { + // (MS) I tested the difference between using Throwable.getStackTrace() and Thread.getStackTrace(), and + // the version using Throwable was surprisingly faster! at least on Java 1.8. See ReflectionBenchmark. + final StackTraceElement[] elements = new Throwable().getStackTrace(); + int i = 0; + for (final StackTraceElement element : elements) { + if (isValid(element)) { + if (i == depth) { + return element; + } + ++i; + } + } + throw new IndexOutOfBoundsException(Integer.toString(depth)); + } + + public static boolean isValid(final StackTraceElement element) { + // ignore native methods (oftentimes are repeated frames) + if (element.isNativeMethod()) { + return false; + } + final String cn = element.getClassName(); + // ignore OpenJDK internal classes involved with reflective invocation + if (cn.startsWith("sun.reflect.")) { + return false; + } + final String mn = element.getMethodName(); + // ignore use of reflection including: + // Method.invoke + // InvocationHandler.invoke + // Constructor.newInstance + if (cn.startsWith("java.lang.reflect.") + && (mn.equals("invoke") || mn.equals("newInstance"))) { + return false; + } + // ignore use of Java 1.9+ reflection classes + if (cn.startsWith("jdk.internal.reflect.")) { + return false; + } + // ignore Class.newInstance + if (cn.equals("java.lang.Class") && mn.equals("newInstance")) { + return false; + } + // ignore use of Java 1.7+ MethodHandle.invokeFoo() methods + if (cn.equals("java.lang.invoke.MethodHandle") && mn.startsWith("invoke")) { + return false; + } + // any others? + return true; + } + + public static Class executeReflectionLogic(int realFramesToSkip) { + // 在 JDK 8 下执行的方法逻辑 if (method == null) throw new IllegalStateException("sun.reflect.Reflection initialization failure."); try { @@ -47,4 +99,25 @@ public static Class getCallerClass(int realFramesToSkip) { } } + public static Class executeStackTraceLogic(int depth) { + // 在 JDK 17 下执行的方法逻辑 + // 解除注释,编译成Class 并且放置到 META-INF/versions/17/com/alipay/sofa/serverless/common/util 下面 + // slower fallback method using stack trace + final StackTraceElement element = getEquivalentStackTraceElement(depth + 1); + try { + return LoaderUtil.loadClass(element.getClassName()); + } catch (final ClassNotFoundException e) { + //continue + } + return null; + } + + public static Class getCallerClass(int realFramesToSkip) { + try { + return executeReflectionLogic(realFramesToSkip); + } catch (Exception e) { + return executeStackTraceLogic(realFramesToSkip); + } + } + } diff --git a/sofa-serverless-runtime/sofa-serverless-common/src/test/java/com/alipay/sofa/serverless/common/ReflectionUtilsTest.java b/sofa-serverless-runtime/sofa-serverless-common/src/test/java/com/alipay/sofa/serverless/common/ReflectionUtilsTest.java new file mode 100644 index 000000000..4de1f5a72 --- /dev/null +++ b/sofa-serverless-runtime/sofa-serverless-common/src/test/java/com/alipay/sofa/serverless/common/ReflectionUtilsTest.java @@ -0,0 +1,58 @@ +/* + * 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 com.alipay.sofa.serverless.common; + +import com.alipay.sofa.serverless.common.util.ReflectionUtils; +import org.junit.Assert; +import org.junit.Test; + +public class ReflectionUtilsTest { + @Test + public void testIsValid() { + StackTraceElement nativeMethodElement = new StackTraceElement("ClassName", "methodName", + "fileName", -2); + Assert.assertFalse(ReflectionUtils.isValid(nativeMethodElement)); + + StackTraceElement sunReflectElement = new StackTraceElement("sun.reflect.ClassName", + "methodName", "fileName", 123); + Assert.assertFalse(ReflectionUtils.isValid(sunReflectElement)); + + StackTraceElement javaReflectInvokeElement = new StackTraceElement( + "java.lang.reflect.ClassName", "invoke", "fileName", 123); + Assert.assertFalse(ReflectionUtils.isValid(javaReflectInvokeElement)); + + StackTraceElement javaReflectNewInstanceElement = new StackTraceElement( + "java.lang.reflect.ClassName", "newInstance", "fileName", 123); + Assert.assertFalse(ReflectionUtils.isValid(javaReflectNewInstanceElement)); + + StackTraceElement jdkInternalReflectElement = new StackTraceElement( + "jdk.internal.reflect.ClassName", "methodName", "fileName", 123); + Assert.assertFalse(ReflectionUtils.isValid(jdkInternalReflectElement)); + + StackTraceElement javaLangClassElement = new StackTraceElement("java.lang.Class", + "newInstance", "fileName", 123); + Assert.assertFalse(ReflectionUtils.isValid(javaLangClassElement)); + + StackTraceElement javaLangInvokeMethodHandleElement = new StackTraceElement( + "java.lang.invoke.MethodHandle", "invokeMethod", "fileName", 123); + Assert.assertFalse(ReflectionUtils.isValid(javaLangInvokeMethodHandleElement)); + + StackTraceElement validElement = new StackTraceElement("ValidClassName", "validMethodName", + "fileName", 123); + Assert.assertTrue(ReflectionUtils.isValid(validElement)); + } +} diff --git a/sofa-serverless-runtime/sofa-serverless-common/src/test/java/com/alipay/sofa/serverless/common/SpringServiceFinderTest.java b/sofa-serverless-runtime/sofa-serverless-common/src/test/java/com/alipay/sofa/serverless/common/SpringServiceFinderTest.java index de42b2c88..77f619448 100644 --- a/sofa-serverless-runtime/sofa-serverless-common/src/test/java/com/alipay/sofa/serverless/common/SpringServiceFinderTest.java +++ b/sofa-serverless-runtime/sofa-serverless-common/src/test/java/com/alipay/sofa/serverless/common/SpringServiceFinderTest.java @@ -37,6 +37,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.util.ReflectionUtils; +import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.List; @@ -118,8 +119,9 @@ public void testSpringServiceFinder() { Assert.assertEquals("module", moduleBean.test()); // test to invoke crossing classloader - URLClassLoader loader = new URLClassLoader( - ((URLClassLoader) ClassLoader.getSystemClassLoader()).getURLs(), null); + + URL url = SpringServiceFinderTest.class.getClassLoader().getResource(""); + URLClassLoader loader = new URLClassLoader(new URL[] { url }, null); Object newModuleBean = null; try { Class aClass = loader @@ -213,4 +215,4 @@ public String test() { } } -} +} \ No newline at end of file