This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-java.git


The following commit(s) were added to refs/heads/main by this push:
     new 35856b4bca Add the virtual thread executor plugin (#751)
35856b4bca is described below

commit 35856b4bca9aa5b077e3c7f67b44a7c02f3f9516
Author: peachisai <[email protected]>
AuthorDate: Sun Mar 9 09:39:41 2025 +0800

    Add the virtual thread executor plugin (#751)
---
 .github/workflows/plugins-jdk21-test.0.yaml        |   1 +
 CHANGES.md                                         |   1 +
 .../network/trace/component/ComponentsDefine.java  |   2 +
 .../apm/agent/core/context/tag/Tags.java           |   5 +
 .../jdk-virtual-thread-executor-plugin/pom.xml     |  46 +++++++++
 .../ThreadPerTaskExecutorConstructInterceptor.java |  33 +++++++
 .../ThreadPerTaskExecutorRunInterceptor.java       |  81 ++++++++++++++++
 ...ThreadPerTaskExecutorFutureInstrumentation.java |  90 ++++++++++++++++++
 ...adPerTaskExecutorTaskRunnerInstrumentation.java |  90 ++++++++++++++++++
 .../src/main/resources/skywalking-plugin.def       |  18 ++++
 apm-sniffer/bootstrap-plugins/pom.xml              |   1 +
 .../java-agent/Application-toolkit-log4j-1.x.md    |   2 +-
 .../service-agent/java-agent/Bootstrap-plugins.md  |   1 +
 .../setup/service-agent/java-agent/Plugin-list.md  |   1 +
 .../bin/startup.sh                                 |  21 +++++
 .../config/expectedData.yaml                       | 101 ++++++++++++++++++++
 .../configuration.yml                              |  22 +++++
 .../jdk-virtual-thread-executor-scenario/pom.xml   | 103 +++++++++++++++++++++
 .../src/main/assembly/assembly.xml                 |  41 ++++++++
 .../testcase/jdk/virtualThread/Application.java    |  73 +++++++++++++++
 .../src/main/resources/application.yaml            |  21 +++++
 .../support-version.list                           |  17 ++++
 22 files changed, 770 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/plugins-jdk21-test.0.yaml 
b/.github/workflows/plugins-jdk21-test.0.yaml
index 2851619f12..87b058284c 100644
--- a/.github/workflows/plugins-jdk21-test.0.yaml
+++ b/.github/workflows/plugins-jdk21-test.0.yaml
@@ -56,6 +56,7 @@ jobs:
       matrix:
         case:
           - spring-6.x-scenario
+          - jdk-virtual-thread-executor-scenario
     steps:
       - uses: actions/checkout@v2
         with:
diff --git a/CHANGES.md b/CHANGES.md
index 2e024d8c17..74ab4201d7 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -5,6 +5,7 @@ Release Notes.
 9.5.0
 ------------------
 
+* Add the virtual thread executor plugin
 
 
 All issues and pull requests are 
[here](https://github.com/apache/skywalking/milestone/236?closed=1)
diff --git 
a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
 
b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
index e10b207ce5..d81ba8c136 100755
--- 
a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
+++ 
b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
@@ -260,4 +260,6 @@ public class ComponentsDefine {
     public static final OfficialComponent SOLON_MVC = new 
OfficialComponent(158, "SolonMVC");
 
     public static final OfficialComponent CAFFEINE = new 
OfficialComponent(160, "Caffeine");
+
+    public static final OfficialComponent THREAD_PER_TASK_EXECUTOR = new 
OfficialComponent(161, "ThreadPerTask-executor");
 }
diff --git 
a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java
 
b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java
index e538241368..18093a453e 100644
--- 
a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java
+++ 
b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java
@@ -155,6 +155,11 @@ public final class Tags {
      */
     public static final StringTag THREAD_ID = new StringTag(23, "thread.id");
 
+    /**
+     * THREAD_CARRIER represents the actual operating system thread that 
carries out the execution of the virtual thread.
+     */
+    public static final StringTag THREAD_CARRIER = new StringTag(24, 
"thread.carrier");
+
     /**
      * Creates a {@code StringTag} with the given key and cache it, if it's 
created before, simply return it without
      * creating a new one.
diff --git 
a/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/pom.xml 
b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/pom.xml
new file mode 100644
index 0000000000..705560aad1
--- /dev/null
+++ b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/pom.xml
@@ -0,0 +1,46 @@
+<!--
+  ~ 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.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <parent>
+        <artifactId>bootstrap-plugins</artifactId>
+        <groupId>org.apache.skywalking</groupId>
+        <version>9.5.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>apm-jdk-virtual-thread-executor-plugin</artifactId>
+    <packaging>jar</packaging>
+
+    <name>apm-jdk-virtual-thread-executor-plugin</name>
+    <url>http://maven.apache.org</url>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-deploy-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git 
a/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPerTaskExecutorConstructInterceptor.java
 
b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPerTaskExecutorConstructInterceptor.java
new file mode 100644
index 0000000000..c8f18193f9
--- /dev/null
+++ 
b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPerTaskExecutorConstructInterceptor.java
@@ -0,0 +1,33 @@
+/*
+ * 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.skywalking.apm.plugin;
+
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
+
+public class ThreadPerTaskExecutorConstructInterceptor implements 
InstanceConstructorInterceptor {
+
+    @Override
+    public void onConstruct(EnhancedInstance objInst, Object[] allArguments) 
throws Throwable {
+        if (ContextManager.isActive()) {
+            objInst.setSkyWalkingDynamicField(ContextManager.capture());
+        }
+    }
+}
diff --git 
a/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPerTaskExecutorRunInterceptor.java
 
b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPerTaskExecutorRunInterceptor.java
new file mode 100644
index 0000000000..9cd9289116
--- /dev/null
+++ 
b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPerTaskExecutorRunInterceptor.java
@@ -0,0 +1,81 @@
+/*
+ * 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.skywalking.apm.plugin;
+
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
+import org.apache.skywalking.apm.agent.core.context.tag.Tags;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+
+import java.lang.reflect.Method;
+
+public class ThreadPerTaskExecutorRunInterceptor implements 
InstanceMethodsAroundInterceptor {
+
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] 
allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws 
Throwable {
+        Object skyWalkingDynamicField = objInst.getSkyWalkingDynamicField();
+        if (skyWalkingDynamicField == null) {
+            return;
+        }
+
+        if (!(skyWalkingDynamicField instanceof ContextSnapshot)) {
+            return;
+        }
+
+        AbstractSpan span = 
ContextManager.createLocalSpan(getOperationName(objInst, method));
+        span.setComponent(ComponentsDefine.THREAD_PER_TASK_EXECUTOR);
+        setCarrierThread(span);
+
+        ContextSnapshot contextSnapshot = (ContextSnapshot) 
skyWalkingDynamicField;
+        ContextManager.continued(contextSnapshot);
+    }
+
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, 
Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
+        if (ContextManager.isActive()) {
+            ContextManager.stopSpan();
+        }
+        return ret;
+    }
+
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, 
Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
+        if (ContextManager.isActive()) {
+            ContextManager.activeSpan().log(t);
+        }
+    }
+
+    private String getOperationName(EnhancedInstance objInst, Method method) {
+        return objInst.getClass().getName() + "." + method.getName();
+    }
+
+    private void setCarrierThread(AbstractSpan span) {
+        String threadInfo = Thread.currentThread().toString();
+        if (threadInfo.startsWith("VirtualThread")) {
+            String[] parts = threadInfo.split("@");
+            if (parts.length >= 1) {
+                Tags.THREAD_CARRIER.set(span, parts[1]);
+            }
+        }
+    }
+}
diff --git 
a/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPerTaskExecutorFutureInstrumentation.java
 
b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPerTaskExecutorFutureInstrumentation.java
new file mode 100644
index 0000000000..3ed5788a1e
--- /dev/null
+++ 
b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPerTaskExecutorFutureInstrumentation.java
@@ -0,0 +1,90 @@
+/*
+ * 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.skywalking.apm.plugin.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import net.bytebuddy.matcher.ElementMatchers;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+import org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.any;
+
+public class ThreadPerTaskExecutorFutureInstrumentation extends 
ClassInstanceMethodsEnhancePluginDefine {
+
+    private static final String ENHANCE_CLASS = 
"java.util.concurrent.ThreadPerTaskExecutor$ThreadBoundFuture";
+
+    private static final String INTERCEPT_RUN_METHOD = "run";
+
+    private static final String INTERCEPT_RUN_HANDLE = 
"org.apache.skywalking.apm.plugin.ThreadPerTaskExecutorRunInterceptor";
+
+    private static final String TASK_RUNNER_CONSTRUCT_METHOD_INTERCEPTOR = 
"org.apache.skywalking.apm.plugin.ThreadPerTaskExecutorConstructInterceptor";
+
+    @Override
+    public boolean isBootstrapInstrumentation() {
+        return true;
+    }
+
+    @Override
+    protected ClassMatch enhanceClass() {
+        return MultiClassNameMatch.byMultiClassMatch(ENHANCE_CLASS);
+    }
+
+    @Override
+    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[]{
+                new ConstructorInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> 
getConstructorMatcher() {
+                        return any();
+                    }
+
+                    @Override
+                    public String getConstructorInterceptor() {
+                        return TASK_RUNNER_CONSTRUCT_METHOD_INTERCEPTOR;
+                    }
+                }
+        };
+    }
+
+    @Override
+    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() 
{
+        return new InstanceMethodsInterceptPoint[]{
+                new InstanceMethodsInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> 
getMethodsMatcher() {
+                        return ElementMatchers.named(INTERCEPT_RUN_METHOD);
+                    }
+
+                    @Override
+                    public String getMethodsInterceptor() {
+                        return INTERCEPT_RUN_HANDLE;
+                    }
+
+                    @Override
+                    public boolean isOverrideArgs() {
+                        return true;
+                    }
+                }
+        };
+    }
+}
diff --git 
a/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPerTaskExecutorTaskRunnerInstrumentation.java
 
b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPerTaskExecutorTaskRunnerInstrumentation.java
new file mode 100644
index 0000000000..9a0efd075f
--- /dev/null
+++ 
b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPerTaskExecutorTaskRunnerInstrumentation.java
@@ -0,0 +1,90 @@
+/*
+ * 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.skywalking.apm.plugin.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import net.bytebuddy.matcher.ElementMatchers;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+import org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.any;
+
+public class ThreadPerTaskExecutorTaskRunnerInstrumentation extends 
ClassInstanceMethodsEnhancePluginDefine {
+
+    private static final String ENHANCE_CLASS = 
"java.util.concurrent.ThreadPerTaskExecutor$TaskRunner";
+
+    private static final String INTERCEPT_RUN_METHOD = "run";
+
+    private static final String INTERCEPT_RUN_HANDLE = 
"org.apache.skywalking.apm.plugin.ThreadPerTaskExecutorRunInterceptor";
+
+    private static final String TASK_RUNNER_CONSTRUCT_METHOD_INTERCEPTOR = 
"org.apache.skywalking.apm.plugin.ThreadPerTaskExecutorConstructInterceptor";
+
+    @Override
+    public boolean isBootstrapInstrumentation() {
+        return true;
+    }
+
+    @Override
+    protected ClassMatch enhanceClass() {
+        return MultiClassNameMatch.byMultiClassMatch(ENHANCE_CLASS);
+    }
+
+    @Override
+    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[]{
+                new ConstructorInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> 
getConstructorMatcher() {
+                        return any();
+                    }
+
+                    @Override
+                    public String getConstructorInterceptor() {
+                        return TASK_RUNNER_CONSTRUCT_METHOD_INTERCEPTOR;
+                    }
+                }
+        };
+    }
+
+    @Override
+    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() 
{
+        return new InstanceMethodsInterceptPoint[]{
+                new InstanceMethodsInterceptPoint() {
+                    @Override
+                    public ElementMatcher<MethodDescription> 
getMethodsMatcher() {
+                        return ElementMatchers.named(INTERCEPT_RUN_METHOD);
+                    }
+
+                    @Override
+                    public String getMethodsInterceptor() {
+                        return INTERCEPT_RUN_HANDLE;
+                    }
+
+                    @Override
+                    public boolean isOverrideArgs() {
+                        return true;
+                    }
+                }
+        };
+    }
+}
diff --git 
a/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/resources/skywalking-plugin.def
 
b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/resources/skywalking-plugin.def
new file mode 100644
index 0000000000..3ab6a970a9
--- /dev/null
+++ 
b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/resources/skywalking-plugin.def
@@ -0,0 +1,18 @@
+# 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.
+
+jdk-virtual-thread-executor-plugin=org.apache.skywalking.apm.plugin.define.ThreadPerTaskExecutorTaskRunnerInstrumentation
+jdk-virtual-thread-executor-plugin=org.apache.skywalking.apm.plugin.define.ThreadPerTaskExecutorFutureInstrumentation
\ No newline at end of file
diff --git a/apm-sniffer/bootstrap-plugins/pom.xml 
b/apm-sniffer/bootstrap-plugins/pom.xml
index 0af18c26df..22de027237 100644
--- a/apm-sniffer/bootstrap-plugins/pom.xml
+++ b/apm-sniffer/bootstrap-plugins/pom.xml
@@ -43,6 +43,7 @@
         <module>jdk-threading-plugin</module>
         <module>jdk-threadpool-plugin</module>
         <module>jdk-forkjoinpool-plugin</module>
+        <module>jdk-virtual-thread-executor-plugin</module>
     </modules>
 
     <dependencies>
diff --git 
a/docs/en/setup/service-agent/java-agent/Application-toolkit-log4j-1.x.md 
b/docs/en/setup/service-agent/java-agent/Application-toolkit-log4j-1.x.md
index b180d164ae..2768fa4a72 100644
--- a/docs/en/setup/service-agent/java-agent/Application-toolkit-log4j-1.x.md
+++ b/docs/en/setup/service-agent/java-agent/Application-toolkit-log4j-1.x.md
@@ -14,7 +14,7 @@
 
log4j.appender.CONSOLE.layout=org.apache.skywalking.apm.toolkit.log.log4j.v1.x.TraceIdPatternLayout
 ```
 
-* set `%T` in `layout.ConversionPattern` ( In 2.0-2016, you should use %x, 
[Why change?](https://github.com/wu-sheng/sky-walking/issues/77) )
+* set `%T` in `layout.ConversionPattern` ( In 2.0-2016, you should use %x, 
[Why change?](https://github.com/apache/skywalking/issues/77) )
 ```properties
 log4j.appender.CONSOLE.layout.ConversionPattern=%d [%T] %-5p %c{1}:%L - %m%n
 ```
diff --git a/docs/en/setup/service-agent/java-agent/Bootstrap-plugins.md 
b/docs/en/setup/service-agent/java-agent/Bootstrap-plugins.md
index 10dd955a9c..7eec71899a 100644
--- a/docs/en/setup/service-agent/java-agent/Bootstrap-plugins.md
+++ b/docs/en/setup/service-agent/java-agent/Bootstrap-plugins.md
@@ -7,6 +7,7 @@ Now, we have the following known bootstrap plugins.
 * Plugin of JDK Callable and Runnable. Agent is compatible with JDK 1.8+
 * Plugin of JDK ThreadPoolExecutor. Agent is compatible with JDK 1.8+
 * Plugin of JDK ForkJoinPool. Agent is compatible with JDK 1.8+
+* Plugin of JDK VirtualThreadExecutor. Agent is compatible with JDK 21+
 
 ### HttpURLConnection Plugin Notice
 The plugin of JDK HttpURLConnection depended on `sun.net.*`. When using Java 
9+, You should add some JVM options as follows:
diff --git a/docs/en/setup/service-agent/java-agent/Plugin-list.md 
b/docs/en/setup/service-agent/java-agent/Plugin-list.md
index 847a81dbec..aa85d4bcb2 100644
--- a/docs/en/setup/service-agent/java-agent/Plugin-list.md
+++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md
@@ -48,6 +48,7 @@
 - jackson-2.x
 - jdk-http-plugin
 - jdk-threading-plugin
+- jdk-virtual-thread-executor-plugin
 - jedis-2.x-3.x
 - jedis-4.x
 - jetty-client-9.0
diff --git 
a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/bin/startup.sh 
b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/bin/startup.sh
new file mode 100644
index 0000000000..ac52eb1f0c
--- /dev/null
+++ b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/bin/startup.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# 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.
+
+home="$(cd "$(dirname $0)"; pwd)"
+
+java -jar ${agent_opts} 
${home}/../libs/jdk-virtual-thread-executor-scenario.jar &
\ No newline at end of file
diff --git 
a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/config/expectedData.yaml
 
b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/config/expectedData.yaml
new file mode 100644
index 0000000000..f2ccbf3ed1
--- /dev/null
+++ 
b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/config/expectedData.yaml
@@ -0,0 +1,101 @@
+# 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.
+segmentItems:
+  - serviceName: jdk-virtual-thread-executor-scenario
+    segmentSize: ge 0
+    segments:
+      - segmentId:  not null
+        spans:
+          - operationName: GET:/case
+            parentSpanId: -1
+            spanId: 0
+            spanLayer: Http
+            startTime: not null
+            endTime: not null
+            componentId: 14
+            isError: false
+            spanType: Entry
+            peer: ''
+            skipAnalysis: false
+            tags:
+              - {key: url, value: 
'http://localhost:8080/virtual-thread-executor-scenario/case'}
+              - {key: http.method, value: GET}
+              - {key: http.status_code, value: '200'}
+      - segmentId:  not null
+        spans:
+          - operationName: /apache/skywalking
+            parentSpanId: 0
+            spanId: 1
+            spanLayer: Http
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 13
+            isError: false
+            spanType: Exit
+            peer: github.com:443
+            skipAnalysis: false
+            tags:
+              - {key: url, value: 'https://github.com/apache/skywalking'}
+              - {key: http.method, value: GET}
+              - {key: http.status_code, value: '200'}
+          - operationName: 
java.util.concurrent.ThreadPerTaskExecutor$TaskRunner.run
+            parentSpanId: -1
+            spanId: 0
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 161
+            isError: false
+            spanType: Local
+            skipAnalysis: false
+            tags:
+              - { key: thread.carrier, value: not null }
+            refs:
+              - { parentEndpoint: 'GET:/case', networkAddress: '', refType: 
CrossThread,
+                parentSpanId: 0, parentTraceSegmentId: not null, 
parentServiceInstance: not
+                    null, parentService: jdk-virtual-thread-executor-scenario, 
traceId: not null }
+
+      - segmentId: not null
+        spans:
+          - operationName: /apache/skywalking
+            parentSpanId: 0
+            spanId: 1
+            spanLayer: Http
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 13
+            isError: false
+            spanType: Exit
+            peer: github.com:443
+            skipAnalysis: false
+            tags:
+              - { key: url, value: 'https://github.com/apache/skywalking' }
+              - { key: http.method, value: GET }
+              - { key: http.status_code, value: '200' }
+          - operationName: 
java.util.concurrent.ThreadPerTaskExecutor$ThreadBoundFuture.run
+            parentSpanId: -1
+            spanId: 0
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 161
+            isError: false
+            spanType: Local
+            skipAnalysis: false
+            tags:
+              - { key: thread.carrier, value: not null }
+            refs:
+              - { parentEndpoint: 'GET:/case', networkAddress: '', refType: 
CrossThread,
+                parentSpanId: 0, parentTraceSegmentId: not null, 
parentServiceInstance: not
+                    null, parentService: jdk-virtual-thread-executor-scenario, 
traceId: not null }
diff --git 
a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/configuration.yml 
b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/configuration.yml
new file mode 100644
index 0000000000..f36c72f82e
--- /dev/null
+++ 
b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/configuration.yml
@@ -0,0 +1,22 @@
+# 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.
+
+type: jvm
+entryService: http://localhost:8080/virtual-thread-executor-scenario/case
+healthCheck: http://localhost:8080/virtual-thread-executor-scenario/healthCheck
+runningMode: with_bootstrap
+withPlugins: apm-jdk-virtual-thread-executor-plugin-*.jar
+startScript: ./bin/startup.sh
diff --git a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/pom.xml 
b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/pom.xml
new file mode 100644
index 0000000000..686330b61a
--- /dev/null
+++ b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/pom.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.apache.skywalking</groupId>
+    <artifactId>jdk-virtual-thread-executor-scenario</artifactId>
+    <version>5.0.0</version>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <compiler.version>21</compiler.version>
+        <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
+        <spring.boot.version>2.7.15</spring.boot.version>
+    </properties>
+
+    <name>skywalking-jdk-virtual-thread-executor-scenario</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <version>2.7.15</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.redisson</groupId>
+            <artifactId>redisson</artifactId>
+            <version>3.33.0</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>jdk-virtual-thread-executor-scenario</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${spring.boot.version}</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>${maven-compiler-plugin.version}</version>
+                <configuration>
+                    <source>${compiler.version}</source>
+                    <target>${compiler.version}</target>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assemble</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                
<descriptor>src/main/assembly/assembly.xml</descriptor>
+                            </descriptors>
+                            <outputDirectory>./target/</outputDirectory>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>21</source>
+                    <target>21</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git 
a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/assembly/assembly.xml
 
b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/assembly/assembly.xml
new file mode 100644
index 0000000000..55f39086fb
--- /dev/null
+++ 
b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/assembly/assembly.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  ~
+  -->
+<assembly
+    
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2";
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+    
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2
 http://maven.apache.org/xsd/assembly-1.1.2.xsd";>
+    <formats>
+        <format>zip</format>
+    </formats>
+
+    <fileSets>
+        <fileSet>
+            <directory>./bin</directory>
+            <fileMode>0775</fileMode>
+        </fileSet>
+    </fileSets>
+
+    <files>
+        <file>
+            <source>./target/jdk-virtual-thread-executor-scenario.jar</source>
+            <outputDirectory>./libs</outputDirectory>
+            <fileMode>0775</fileMode>
+        </file>
+    </files>
+</assembly>
\ No newline at end of file
diff --git 
a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/virtualThread/Application.java
 
b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/virtualThread/Application.java
new file mode 100644
index 0000000000..57aef5d5b6
--- /dev/null
+++ 
b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/virtualThread/Application.java
@@ -0,0 +1,73 @@
+/*
+ * 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 test.apache.skywalking.apm.testcase.jdk.virtualThread;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+@SpringBootApplication
+public class Application {
+
+    public static void main(String[] args) {
+        SpringApplication.run(Application.class, args);
+    }
+
+    @Bean
+    public RestTemplate restTemplate() {
+        return new RestTemplate();
+    }
+
+    @RestController
+    static class TestController {
+        private final RestTemplate restTemplate;
+        private final ExecutorService executorService;
+
+        public TestController(final RestTemplate restTemplate) {
+            this.restTemplate = restTemplate;
+            this.executorService = Executors.newVirtualThreadPerTaskExecutor();
+        }
+
+        @GetMapping("/healthCheck")
+        public String healthCheck() {
+            return "Success";
+        }
+
+        @GetMapping("/case")
+        public String testCase() throws ExecutionException, 
InterruptedException {
+            Runnable runnable = () -> 
restTemplate.getForEntity("https://github.com/apache/skywalking";, String.class);
+            executorService.execute(runnable);
+
+            Callable callable = () -> {
+                
restTemplate.getForEntity("https://github.com/apache/skywalking";, String.class);
+                return "success";
+            };
+            executorService.submit(callable).get();
+
+            return "success";
+        }
+    }
+}
diff --git 
a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/resources/application.yaml
 
b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/resources/application.yaml
new file mode 100644
index 0000000000..0ddde72c7c
--- /dev/null
+++ 
b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/resources/application.yaml
@@ -0,0 +1,21 @@
+# 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.
+
+server:
+  port: 8080
+  servlet:
+    context-path: /virtual-thread-executor-scenario
+
diff --git 
a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/support-version.list
 
b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/support-version.list
new file mode 100644
index 0000000000..feef03cdea
--- /dev/null
+++ 
b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/support-version.list
@@ -0,0 +1,17 @@
+# 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.
+
+all
\ No newline at end of file


Reply via email to