You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pekko.apache.org by he...@apache.org on 2026/07/06 08:30:15 UTC
(pekko-http) branch refactor/replace-reflection-with-methodhandles created (now 0269df092)
This is an automated email from the ASF dual-hosted git repository.
He-Pin pushed a change to branch refactor/replace-reflection-with-methodhandles
in repository https://gitbox.apache.org/repos/asf/pekko-http.git
at 0269df092 refactor: replace java.lang.reflect with MethodHandle/VarHandle for JIT optimization
This branch includes the following new commits:
new 0269df092 refactor: replace java.lang.reflect with MethodHandle/VarHandle for JIT optimization
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pekko.apache.org
For additional commands, e-mail: commits-help@pekko.apache.org
(pekko-http) 01/01: refactor: replace java.lang.reflect with MethodHandle/VarHandle for JIT optimization
Posted by he...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
He-Pin pushed a commit to branch refactor/replace-reflection-with-methodhandles
in repository https://gitbox.apache.org/repos/asf/pekko-http.git
commit 0269df0924db824cd446ad12e0525893fb417a8d
Author: 虎鸣 <he...@alibaba-inc.com>
AuthorDate: Mon Jul 6 16:29:58 2026 +0800
refactor: replace java.lang.reflect with MethodHandle/VarHandle for JIT optimization
Motivation:
java.lang.reflect Method.invoke and Constructor.newInstance bypass JIT
inlining, adding overhead to build-time aggregation calls and test code.
Modification:
- SbtInternalAccess: replace Method.invoke with MethodHandle.invoke via
unreflect for Aggregation.showRun calls
- Http2ServerSpec: replace Field.get with VarHandle.get via
unreflectVarHandle for ManualProbe.probe field access
- TurkishISpec: replace Constructor.newInstance with MethodHandle.invoke
via unreflectConstructor for HttpCharsets$ instantiation
Result:
MethodHandle and VarHandle enable JIT inlining, eliminating reflection
overhead in both build-time and test code paths.
Tests:
- sbt "http2-tests / Test / compile" - success
- sbt "http-core / Test / compile" - success
References:
None - internal refactoring
---
.../org/apache/pekko/http/scaladsl/model/TurkishISpec.scala | 9 ++++++---
.../apache/pekko/http/impl/engine/http2/Http2ServerSpec.scala | 10 +++++++---
project/SbtInternalAccess.scala | 8 +++++---
3 files changed, 18 insertions(+), 9 deletions(-)
diff --git a/http-core/src/test/scala/org/apache/pekko/http/scaladsl/model/TurkishISpec.scala b/http-core/src/test/scala/org/apache/pekko/http/scaladsl/model/TurkishISpec.scala
index 58d6a89f6..5ac7ec0cb 100644
--- a/http-core/src/test/scala/org/apache/pekko/http/scaladsl/model/TurkishISpec.scala
+++ b/http-core/src/test/scala/org/apache/pekko/http/scaladsl/model/TurkishISpec.scala
@@ -13,6 +13,7 @@
package org.apache.pekko.http.scaladsl.model
+import java.lang.invoke.MethodHandles
import java.util.Locale
import org.apache.pekko.http.impl.util._
import org.scalatest.matchers.should.Matchers
@@ -21,8 +22,10 @@ import org.scalatest.wordspec.AnyWordSpec
class TurkishISpec extends AnyWordSpec with Matchers {
"Model" should {
"not suffer from turkish-i problem" in {
- val charsetCons = Class.forName("org.apache.pekko.http.scaladsl.model.HttpCharsets$").getDeclaredConstructor()
- charsetCons.setAccessible(true)
+ val charsetClass = Class.forName("org.apache.pekko.http.scaladsl.model.HttpCharsets$")
+ val charsetCtor = charsetClass.getDeclaredConstructor()
+ charsetCtor.setAccessible(true)
+ val charsetHandle = MethodHandles.lookup().unreflectConstructor(charsetCtor)
val previousLocale = Locale.getDefault
@@ -34,7 +37,7 @@ class TurkishISpec extends AnyWordSpec with Matchers {
// demonstrate difference between toRootLowerCase and toLowerCase(turkishLocale)
(testString.toLowerCase should not).equal(testString.toRootLowerCase)
- val newCharsets = charsetCons.newInstance().asInstanceOf[HttpCharsets.type]
+ val newCharsets = charsetHandle.invoke().asInstanceOf[HttpCharsets.type]
newCharsets.getForKey("iso-8859-1") shouldEqual Some(newCharsets.`ISO-8859-1`)
} finally {
Locale.setDefault(previousLocale)
diff --git a/http2-tests/src/test/scala/org/apache/pekko/http/impl/engine/http2/Http2ServerSpec.scala b/http2-tests/src/test/scala/org/apache/pekko/http/impl/engine/http2/Http2ServerSpec.scala
index 573a96335..bc2b19b7e 100644
--- a/http2-tests/src/test/scala/org/apache/pekko/http/impl/engine/http2/Http2ServerSpec.scala
+++ b/http2-tests/src/test/scala/org/apache/pekko/http/impl/engine/http2/Http2ServerSpec.scala
@@ -13,6 +13,7 @@
package org.apache.pekko.http.impl.engine.http2
+import java.lang.invoke.MethodHandles
import javax.net.ssl.SSLContext
import scala.collection.immutable
@@ -907,10 +908,13 @@ class Http2ServerSpec extends Http2SpecWithMaterializer("""
def fulfillDemandWithin(publisherProbe: TestPublisher.Probe[?], timeout: FiniteDuration)(
body: => Unit): Unit = {
// HACK to support `expectRequest` with a timeout
+ val probeHandle = {
+ val probeField = classOf[ManualProbe[?]].getDeclaredField("probe")
+ probeField.setAccessible(true)
+ MethodHandles.lookup().unreflectVarHandle(probeField)
+ }
def within[T](publisherProbe: TestPublisher.Probe[?], dur: FiniteDuration)(t: => T): T = {
- val field = classOf[ManualProbe[?]].getDeclaredField("probe")
- field.setAccessible(true)
- field.get(publisherProbe).asInstanceOf[TestProbe].within(dur)(t)
+ probeHandle.get(publisherProbe).asInstanceOf[TestProbe].within(dur)(t)
}
def expectRequest(timeout: FiniteDuration): Long =
within(publisherProbe, timeout)(publisherProbe.expectRequest())
diff --git a/project/SbtInternalAccess.scala b/project/SbtInternalAccess.scala
index bd56f21b9..1ed158b73 100644
--- a/project/SbtInternalAccess.scala
+++ b/project/SbtInternalAccess.scala
@@ -13,16 +13,18 @@
package sbt {
package object access {
+ import java.lang.invoke.MethodHandles
+
type Aggregation = sbt.internal.Aggregation
val Aggregation = sbt.internal.Aggregation
- private val showRunMethod = {
+ private val showRunHandle = {
val method = Class.forName("sbt.internal.Aggregation$").getDeclaredMethods.find(_.getName == "showRun").get
method.setAccessible(true)
- method
+ MethodHandles.lookup().unreflect(method)
}
def AggregationShowRun[T](complete: sbt.internal.Aggregation.Complete[T],
show: sbt.internal.Aggregation.ShowConfig)(
- implicit display: Show[ScopedKey[?]]): Unit = showRunMethod.invoke(Aggregation, complete, show, display)
+ implicit display: Show[ScopedKey[?]]): Unit = showRunHandle.invoke(Aggregation, complete, show, display)
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pekko.apache.org
For additional commands, e-mail: commits-help@pekko.apache.org