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-graalvm-distro.git
The following commit(s) were added to refs/heads/main by this push:
new e438f0f Sync with upstream submodule: VirtualThreads,
ExporterSetting, oap.yaml, warm/cold config
e438f0f is described below
commit e438f0fd7514fc45b8e648777ffdd6a4a623007f
Author: Wu Sheng <[email protected]>
AuthorDate: Wed Feb 25 20:13:11 2026 +0800
Sync with upstream submodule: VirtualThreads, ExporterSetting, oap.yaml,
warm/cold config
- Update skywalking submodule to a0cec0c
- Add VirtualThreads replacement (direct JDK 25 API, no reflection)
- Update HierarchyService to use VirtualThreads.createScheduledExecutor()
- Fix ExporterSetting: bufferChannelSize/bufferChannelNum -> bufferSize
- Handle BanyanDB warm/cold Stage config in YamlConfigLoaderUtils
(extract shared copyToGroupResource with deferred stage processing)
- Update oap.yaml metric label change (kind+metricName -> slot)
- Update SHA-256 hashes for changed upstream files
---
.../server/library/util/YamlConfigLoaderUtils.java | 483 +++------------------
.../skywalking/oap/server/graalvm/mal/OapTest.java | 5 +-
.../resources/precompiled-yaml-sha256.properties | 2 +-
.../resources/replacement-source-sha256.properties | 4 +-
oap-libs-for-graalvm/CLAUDE.md | 12 +-
.../library-util-for-graalvm/pom.xml | 1 +
.../oap/server/library/util/VirtualThreads.java | 97 +++++
.../server/core/hierarchy/HierarchyService.java | 15 +-
skywalking | 2 +-
9 files changed, 191 insertions(+), 430 deletions(-)
diff --git
a/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/library/util/YamlConfigLoaderUtils.java
b/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/library/util/YamlConfigLoaderUtils.java
index 649f154..077128a 100644
---
a/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/library/util/YamlConfigLoaderUtils.java
+++
b/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/library/util/YamlConfigLoaderUtils.java
@@ -1438,11 +1438,8 @@ public class YamlConfigLoaderUtils {
case "gRPCTargetPort":
cfg.setGRPCTargetPort((int) value);
break;
- case "bufferChannelSize":
- cfg.setBufferChannelSize((int) value);
- break;
- case "bufferChannelNum":
- cfg.setBufferChannelNum((int) value);
+ case "bufferSize":
+ cfg.setBufferSize((int) value);
break;
case "enableKafkaTrace":
cfg.setEnableKafkaTrace((boolean) value);
@@ -1596,10 +1593,18 @@ public class YamlConfigLoaderUtils {
}
}
- @SuppressWarnings("unchecked")
- private static void copyToRecordsNormal(
- final BanyanDBStorageConfig.RecordsNormal cfg, final Properties
src,
- final String moduleName, final String providerName) {
+ /**
+ * Copies GroupResource fields (shardNum, segmentInterval, ttl, replicas,
enableWarmStage,
+ * enableColdStage) and processes nested warm/cold Stage sections.
+ * Mirrors upstream BanyanDBConfigLoader.copyStages() logic: warm/cold are
deferred
+ * until after all simple fields are set, so
enableWarmStage/enableColdStage flags
+ * are available regardless of Properties iteration order.
+ */
+ private static void copyToGroupResource(
+ final BanyanDBStorageConfig.GroupResource cfg, final Properties
src,
+ final String moduleName, final String providerName) throws
IllegalAccessException {
+ Properties warmProps = null;
+ Properties coldProps = null;
final Enumeration<?> propertyNames = src.propertyNames();
while (propertyNames.hasMoreElements()) {
final String key = (String) propertyNames.nextElement();
@@ -1630,474 +1635,120 @@ public class YamlConfigLoaderUtils {
case "additionalLifecycleStages":
cfg.setAdditionalLifecycleStages((List) value);
break;
+ case "warm":
+ if (value instanceof Properties) {
+ warmProps = (Properties) value;
+ }
+ break;
+ case "cold":
+ if (value instanceof Properties) {
+ coldProps = (Properties) value;
+ }
+ break;
default:
log.warn("{} setting is not supported in {} provider of {}
module",
key, providerName, moduleName);
break;
}
}
+ if (cfg.isEnableWarmStage() && warmProps != null) {
+ BanyanDBStorageConfig.Stage warm = new
BanyanDBStorageConfig.Stage();
+ warm.setName(BanyanDBStorageConfig.StageName.warm);
+ copyProperties(warm, warmProps, moduleName, providerName);
+ cfg.getAdditionalLifecycleStages().add(warm);
+
cfg.getDefaultQueryStages().add(BanyanDBStorageConfig.StageName.warm.name());
+ }
+ if (cfg.isEnableColdStage() && coldProps != null) {
+ BanyanDBStorageConfig.Stage cold = new
BanyanDBStorageConfig.Stage();
+ cold.setName(BanyanDBStorageConfig.StageName.cold);
+ cold.setClose(true);
+ copyProperties(cold, coldProps, moduleName, providerName);
+ cfg.getAdditionalLifecycleStages().add(cold);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private static void copyToRecordsNormal(
+ final BanyanDBStorageConfig.RecordsNormal cfg, final Properties
src,
+ final String moduleName, final String providerName) throws
IllegalAccessException {
+ copyToGroupResource(cfg, src, moduleName, providerName);
}
@SuppressWarnings("unchecked")
private static void copyToRecordsLog(
final BanyanDBStorageConfig.RecordsLog cfg, final Properties src,
- final String moduleName, final String providerName) {
- final Enumeration<?> propertyNames = src.propertyNames();
- while (propertyNames.hasMoreElements()) {
- final String key = (String) propertyNames.nextElement();
- final Object value = src.get(key);
- log.debug("{}.{} config: {} = {}", moduleName, providerName, key,
value);
- switch (key) {
- case "shardNum":
- cfg.setShardNum((int) value);
- break;
- case "segmentInterval":
- cfg.setSegmentInterval((int) value);
- break;
- case "ttl":
- cfg.setTtl((int) value);
- break;
- case "replicas":
- cfg.setReplicas((int) value);
- break;
- case "enableWarmStage":
- cfg.setEnableWarmStage((boolean) value);
- break;
- case "enableColdStage":
- cfg.setEnableColdStage((boolean) value);
- break;
- case "defaultQueryStages":
- cfg.setDefaultQueryStages((List) value);
- break;
- case "additionalLifecycleStages":
- cfg.setAdditionalLifecycleStages((List) value);
- break;
- default:
- log.warn("{} setting is not supported in {} provider of {}
module",
- key, providerName, moduleName);
- break;
- }
- }
+ final String moduleName, final String providerName) throws
IllegalAccessException {
+ copyToGroupResource(cfg, src, moduleName, providerName);
}
@SuppressWarnings("unchecked")
private static void copyToTrace(
final BanyanDBStorageConfig.Trace cfg, final Properties src,
- final String moduleName, final String providerName) {
- final Enumeration<?> propertyNames = src.propertyNames();
- while (propertyNames.hasMoreElements()) {
- final String key = (String) propertyNames.nextElement();
- final Object value = src.get(key);
- log.debug("{}.{} config: {} = {}", moduleName, providerName, key,
value);
- switch (key) {
- case "shardNum":
- cfg.setShardNum((int) value);
- break;
- case "segmentInterval":
- cfg.setSegmentInterval((int) value);
- break;
- case "ttl":
- cfg.setTtl((int) value);
- break;
- case "replicas":
- cfg.setReplicas((int) value);
- break;
- case "enableWarmStage":
- cfg.setEnableWarmStage((boolean) value);
- break;
- case "enableColdStage":
- cfg.setEnableColdStage((boolean) value);
- break;
- case "defaultQueryStages":
- cfg.setDefaultQueryStages((List) value);
- break;
- case "additionalLifecycleStages":
- cfg.setAdditionalLifecycleStages((List) value);
- break;
- default:
- log.warn("{} setting is not supported in {} provider of {}
module",
- key, providerName, moduleName);
- break;
- }
- }
+ final String moduleName, final String providerName) throws
IllegalAccessException {
+ copyToGroupResource(cfg, src, moduleName, providerName);
}
@SuppressWarnings("unchecked")
private static void copyToZipkinTrace(
final BanyanDBStorageConfig.ZipkinTrace cfg, final Properties src,
- final String moduleName, final String providerName) {
- final Enumeration<?> propertyNames = src.propertyNames();
- while (propertyNames.hasMoreElements()) {
- final String key = (String) propertyNames.nextElement();
- final Object value = src.get(key);
- log.debug("{}.{} config: {} = {}", moduleName, providerName, key,
value);
- switch (key) {
- case "shardNum":
- cfg.setShardNum((int) value);
- break;
- case "segmentInterval":
- cfg.setSegmentInterval((int) value);
- break;
- case "ttl":
- cfg.setTtl((int) value);
- break;
- case "replicas":
- cfg.setReplicas((int) value);
- break;
- case "enableWarmStage":
- cfg.setEnableWarmStage((boolean) value);
- break;
- case "enableColdStage":
- cfg.setEnableColdStage((boolean) value);
- break;
- case "defaultQueryStages":
- cfg.setDefaultQueryStages((List) value);
- break;
- case "additionalLifecycleStages":
- cfg.setAdditionalLifecycleStages((List) value);
- break;
- default:
- log.warn("{} setting is not supported in {} provider of {}
module",
- key, providerName, moduleName);
- break;
- }
- }
+ final String moduleName, final String providerName) throws
IllegalAccessException {
+ copyToGroupResource(cfg, src, moduleName, providerName);
}
@SuppressWarnings("unchecked")
private static void copyToRecordsTrace(
final BanyanDBStorageConfig.RecordsTrace cfg, final Properties src,
- final String moduleName, final String providerName) {
- final Enumeration<?> propertyNames = src.propertyNames();
- while (propertyNames.hasMoreElements()) {
- final String key = (String) propertyNames.nextElement();
- final Object value = src.get(key);
- log.debug("{}.{} config: {} = {}", moduleName, providerName, key,
value);
- switch (key) {
- case "shardNum":
- cfg.setShardNum((int) value);
- break;
- case "segmentInterval":
- cfg.setSegmentInterval((int) value);
- break;
- case "ttl":
- cfg.setTtl((int) value);
- break;
- case "replicas":
- cfg.setReplicas((int) value);
- break;
- case "enableWarmStage":
- cfg.setEnableWarmStage((boolean) value);
- break;
- case "enableColdStage":
- cfg.setEnableColdStage((boolean) value);
- break;
- case "defaultQueryStages":
- cfg.setDefaultQueryStages((List) value);
- break;
- case "additionalLifecycleStages":
- cfg.setAdditionalLifecycleStages((List) value);
- break;
- default:
- log.warn("{} setting is not supported in {} provider of {}
module",
- key, providerName, moduleName);
- break;
- }
- }
+ final String moduleName, final String providerName) throws
IllegalAccessException {
+ copyToGroupResource(cfg, src, moduleName, providerName);
}
@SuppressWarnings("unchecked")
private static void copyToRecordsZipkinTrace(
final BanyanDBStorageConfig.RecordsZipkinTrace cfg, final
Properties src,
- final String moduleName, final String providerName) {
- final Enumeration<?> propertyNames = src.propertyNames();
- while (propertyNames.hasMoreElements()) {
- final String key = (String) propertyNames.nextElement();
- final Object value = src.get(key);
- log.debug("{}.{} config: {} = {}", moduleName, providerName, key,
value);
- switch (key) {
- case "shardNum":
- cfg.setShardNum((int) value);
- break;
- case "segmentInterval":
- cfg.setSegmentInterval((int) value);
- break;
- case "ttl":
- cfg.setTtl((int) value);
- break;
- case "replicas":
- cfg.setReplicas((int) value);
- break;
- case "enableWarmStage":
- cfg.setEnableWarmStage((boolean) value);
- break;
- case "enableColdStage":
- cfg.setEnableColdStage((boolean) value);
- break;
- case "defaultQueryStages":
- cfg.setDefaultQueryStages((List) value);
- break;
- case "additionalLifecycleStages":
- cfg.setAdditionalLifecycleStages((List) value);
- break;
- default:
- log.warn("{} setting is not supported in {} provider of {}
module",
- key, providerName, moduleName);
- break;
- }
- }
+ final String moduleName, final String providerName) throws
IllegalAccessException {
+ copyToGroupResource(cfg, src, moduleName, providerName);
}
@SuppressWarnings("unchecked")
private static void copyToRecordsBrowserErrorLog(
final BanyanDBStorageConfig.RecordsBrowserErrorLog cfg, final
Properties src,
- final String moduleName, final String providerName) {
- final Enumeration<?> propertyNames = src.propertyNames();
- while (propertyNames.hasMoreElements()) {
- final String key = (String) propertyNames.nextElement();
- final Object value = src.get(key);
- log.debug("{}.{} config: {} = {}", moduleName, providerName, key,
value);
- switch (key) {
- case "shardNum":
- cfg.setShardNum((int) value);
- break;
- case "segmentInterval":
- cfg.setSegmentInterval((int) value);
- break;
- case "ttl":
- cfg.setTtl((int) value);
- break;
- case "replicas":
- cfg.setReplicas((int) value);
- break;
- case "enableWarmStage":
- cfg.setEnableWarmStage((boolean) value);
- break;
- case "enableColdStage":
- cfg.setEnableColdStage((boolean) value);
- break;
- case "defaultQueryStages":
- cfg.setDefaultQueryStages((List) value);
- break;
- case "additionalLifecycleStages":
- cfg.setAdditionalLifecycleStages((List) value);
- break;
- default:
- log.warn("{} setting is not supported in {} provider of {}
module",
- key, providerName, moduleName);
- break;
- }
- }
+ final String moduleName, final String providerName) throws
IllegalAccessException {
+ copyToGroupResource(cfg, src, moduleName, providerName);
}
@SuppressWarnings("unchecked")
private static void copyToMetricsMin(
final BanyanDBStorageConfig.MetricsMin cfg, final Properties src,
- final String moduleName, final String providerName) {
- final Enumeration<?> propertyNames = src.propertyNames();
- while (propertyNames.hasMoreElements()) {
- final String key = (String) propertyNames.nextElement();
- final Object value = src.get(key);
- log.debug("{}.{} config: {} = {}", moduleName, providerName, key,
value);
- switch (key) {
- case "shardNum":
- cfg.setShardNum((int) value);
- break;
- case "segmentInterval":
- cfg.setSegmentInterval((int) value);
- break;
- case "ttl":
- cfg.setTtl((int) value);
- break;
- case "replicas":
- cfg.setReplicas((int) value);
- break;
- case "enableWarmStage":
- cfg.setEnableWarmStage((boolean) value);
- break;
- case "enableColdStage":
- cfg.setEnableColdStage((boolean) value);
- break;
- case "defaultQueryStages":
- cfg.setDefaultQueryStages((List) value);
- break;
- case "additionalLifecycleStages":
- cfg.setAdditionalLifecycleStages((List) value);
- break;
- default:
- log.warn("{} setting is not supported in {} provider of {}
module",
- key, providerName, moduleName);
- break;
- }
- }
+ final String moduleName, final String providerName) throws
IllegalAccessException {
+ copyToGroupResource(cfg, src, moduleName, providerName);
}
@SuppressWarnings("unchecked")
private static void copyToMetricsHour(
final BanyanDBStorageConfig.MetricsHour cfg, final Properties src,
- final String moduleName, final String providerName) {
- final Enumeration<?> propertyNames = src.propertyNames();
- while (propertyNames.hasMoreElements()) {
- final String key = (String) propertyNames.nextElement();
- final Object value = src.get(key);
- log.debug("{}.{} config: {} = {}", moduleName, providerName, key,
value);
- switch (key) {
- case "shardNum":
- cfg.setShardNum((int) value);
- break;
- case "segmentInterval":
- cfg.setSegmentInterval((int) value);
- break;
- case "ttl":
- cfg.setTtl((int) value);
- break;
- case "replicas":
- cfg.setReplicas((int) value);
- break;
- case "enableWarmStage":
- cfg.setEnableWarmStage((boolean) value);
- break;
- case "enableColdStage":
- cfg.setEnableColdStage((boolean) value);
- break;
- case "defaultQueryStages":
- cfg.setDefaultQueryStages((List) value);
- break;
- case "additionalLifecycleStages":
- cfg.setAdditionalLifecycleStages((List) value);
- break;
- default:
- log.warn("{} setting is not supported in {} provider of {}
module",
- key, providerName, moduleName);
- break;
- }
- }
+ final String moduleName, final String providerName) throws
IllegalAccessException {
+ copyToGroupResource(cfg, src, moduleName, providerName);
}
@SuppressWarnings("unchecked")
private static void copyToMetricsDay(
final BanyanDBStorageConfig.MetricsDay cfg, final Properties src,
- final String moduleName, final String providerName) {
- final Enumeration<?> propertyNames = src.propertyNames();
- while (propertyNames.hasMoreElements()) {
- final String key = (String) propertyNames.nextElement();
- final Object value = src.get(key);
- log.debug("{}.{} config: {} = {}", moduleName, providerName, key,
value);
- switch (key) {
- case "shardNum":
- cfg.setShardNum((int) value);
- break;
- case "segmentInterval":
- cfg.setSegmentInterval((int) value);
- break;
- case "ttl":
- cfg.setTtl((int) value);
- break;
- case "replicas":
- cfg.setReplicas((int) value);
- break;
- case "enableWarmStage":
- cfg.setEnableWarmStage((boolean) value);
- break;
- case "enableColdStage":
- cfg.setEnableColdStage((boolean) value);
- break;
- case "defaultQueryStages":
- cfg.setDefaultQueryStages((List) value);
- break;
- case "additionalLifecycleStages":
- cfg.setAdditionalLifecycleStages((List) value);
- break;
- default:
- log.warn("{} setting is not supported in {} provider of {}
module",
- key, providerName, moduleName);
- break;
- }
- }
+ final String moduleName, final String providerName) throws
IllegalAccessException {
+ copyToGroupResource(cfg, src, moduleName, providerName);
}
@SuppressWarnings("unchecked")
private static void copyToMetadata(
final BanyanDBStorageConfig.Metadata cfg, final Properties src,
- final String moduleName, final String providerName) {
- final Enumeration<?> propertyNames = src.propertyNames();
- while (propertyNames.hasMoreElements()) {
- final String key = (String) propertyNames.nextElement();
- final Object value = src.get(key);
- log.debug("{}.{} config: {} = {}", moduleName, providerName, key,
value);
- switch (key) {
- case "shardNum":
- cfg.setShardNum((int) value);
- break;
- case "segmentInterval":
- cfg.setSegmentInterval((int) value);
- break;
- case "ttl":
- cfg.setTtl((int) value);
- break;
- case "replicas":
- cfg.setReplicas((int) value);
- break;
- case "enableWarmStage":
- cfg.setEnableWarmStage((boolean) value);
- break;
- case "enableColdStage":
- cfg.setEnableColdStage((boolean) value);
- break;
- case "defaultQueryStages":
- cfg.setDefaultQueryStages((List) value);
- break;
- case "additionalLifecycleStages":
- cfg.setAdditionalLifecycleStages((List) value);
- break;
- default:
- log.warn("{} setting is not supported in {} provider of {}
module",
- key, providerName, moduleName);
- break;
- }
- }
+ final String moduleName, final String providerName) throws
IllegalAccessException {
+ copyToGroupResource(cfg, src, moduleName, providerName);
}
@SuppressWarnings("unchecked")
private static void copyToProperty(
final BanyanDBStorageConfig.Property cfg, final Properties src,
- final String moduleName, final String providerName) {
- final Enumeration<?> propertyNames = src.propertyNames();
- while (propertyNames.hasMoreElements()) {
- final String key = (String) propertyNames.nextElement();
- final Object value = src.get(key);
- log.debug("{}.{} config: {} = {}", moduleName, providerName, key,
value);
- switch (key) {
- case "shardNum":
- cfg.setShardNum((int) value);
- break;
- case "segmentInterval":
- cfg.setSegmentInterval((int) value);
- break;
- case "ttl":
- cfg.setTtl((int) value);
- break;
- case "replicas":
- cfg.setReplicas((int) value);
- break;
- case "enableWarmStage":
- cfg.setEnableWarmStage((boolean) value);
- break;
- case "enableColdStage":
- cfg.setEnableColdStage((boolean) value);
- break;
- case "defaultQueryStages":
- cfg.setDefaultQueryStages((List) value);
- break;
- case "additionalLifecycleStages":
- cfg.setAdditionalLifecycleStages((List) value);
- break;
- default:
- log.warn("{} setting is not supported in {} provider of {}
module",
- key, providerName, moduleName);
- break;
- }
- }
+ final String moduleName, final String providerName) throws
IllegalAccessException {
+ copyToGroupResource(cfg, src, moduleName, providerName);
}
@SuppressWarnings("unchecked")
diff --git
a/oap-graalvm-server/src/test/java/org/apache/skywalking/oap/server/graalvm/mal/OapTest.java
b/oap-graalvm-server/src/test/java/org/apache/skywalking/oap/server/graalvm/mal/OapTest.java
index 906b64d..bb9534c 100644
---
a/oap-graalvm-server/src/test/java/org/apache/skywalking/oap/server/graalvm/mal/OapTest.java
+++
b/oap-graalvm-server/src/test/java/org/apache/skywalking/oap/server/graalvm/mal/OapTest.java
@@ -88,7 +88,7 @@ class OapTest extends MALScriptComparisonBase {
* # --- Metrics Aggregation (tagEqual + conditional rewrite) ---
* metrics_aggregation{...,dimensionality="minute",level="1"} 100.0
* metrics_aggregation{...,dimensionality="minute",level="2"} 50.0
- *
metrics_aggregation_queue_used_percentage{...,level="1",kind="metrics",metricName="test_metric"}
75.0
+ * metrics_aggregation_queue_used_percentage{...,level="1",slot="0"} 75.0
*
* # --- Persistence ---
* persistence_timer_bulk_execute_latency{...le buckets...} histogram
@@ -244,8 +244,7 @@ class OapTest extends MALScriptComparisonBase {
.labels(ImmutableMap.<String, String>builder()
.putAll(scope)
.put("level", "1")
- .put("kind", "metrics")
- .put("metricName", "test_metric")
+ .put("slot", "0")
.build())
.value(75.0 * scale).timestamp(timestamp).build()
).build())
diff --git
a/oap-graalvm-server/src/test/resources/precompiled-yaml-sha256.properties
b/oap-graalvm-server/src/test/resources/precompiled-yaml-sha256.properties
index 5b92f60..d36eae5 100644
--- a/oap-graalvm-server/src/test/resources/precompiled-yaml-sha256.properties
+++ b/oap-graalvm-server/src/test/resources/precompiled-yaml-sha256.properties
@@ -77,7 +77,7 @@
otel-rules/mysql/mysql-service.yaml=8d912d600c27073a5b4cb14ab4e99869157c1e230274
otel-rules/nginx/nginx-endpoint.yaml=5c8ff99f9324faa8451f32cadd9d14c247e3fffc72cb717295eae7e428a907f9
otel-rules/nginx/nginx-instance.yaml=999269ade04346cc22dbcd1a761128f09afc51c1e44ea0a01ba333caee19190c
otel-rules/nginx/nginx-service.yaml=fdacf1236821635763a601e5146d042c3aa10db69c631e115b8d08a68e9ba896
-otel-rules/oap.yaml=69499222f5897af16d3d42c082420403d053d19b38888006786f59cbfd65f216
+otel-rules/oap.yaml=6a61b77b0200ac35fac18d9cd3cfca425c6009461e58a8b9d5040ff6c0410d08
otel-rules/postgresql/postgresql-instance.yaml=6e060619d9f9c0fff5607cc59207e9bafd8f1767cd3dcdee48fe4561644388d3
otel-rules/postgresql/postgresql-service.yaml=8c19e9b218241c0c4deb2affd863a2a36950be90b93867002deef427a417a412
otel-rules/pulsar/pulsar-broker.yaml=eec34a2a75efdbd59830743c8b8e2584bfcb2ab769dac3b4506534b758fecb16
diff --git
a/oap-graalvm-server/src/test/resources/replacement-source-sha256.properties
b/oap-graalvm-server/src/test/resources/replacement-source-sha256.properties
index 17cee20..70d746e 100644
--- a/oap-graalvm-server/src/test/resources/replacement-source-sha256.properties
+++ b/oap-graalvm-server/src/test/resources/replacement-source-sha256.properties
@@ -35,7 +35,7 @@
skywalking/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server
skywalking/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleConfig.java
= f17b294a952670c00ef0b26059cc7fdf458ced0861c5c00210594ba4953edf30
# Java-backed closures instead of GroovyShell
skywalking/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/config/HierarchyDefinitionService.java
= ffadc2cb0a3cfe85b53b3d7fbd74505c7e528f187fd6dc615ede523642bb6c26
-skywalking/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/hierarchy/HierarchyService.java
= 600eaa0c5f5d873792997ece22fb4560e422b987d374d0ea0667e855b4f28d96
+skywalking/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/hierarchy/HierarchyService.java
= f4fc740467b43741e6813ad8cb94bdc42e63965455627bb147faafaf97a76e77
# --- meter-analyzer-for-graalvm ---
# MAL DSL: loads transpiled MalExpression from manifest
@@ -78,6 +78,8 @@
skywalking/oap-server/server-library/library-module/src/main/java/org/apache/sky
# --- library-util-for-graalvm ---
# Config loading: type-dispatch with Lombok setters instead of reflection
skywalking/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/YamlConfigLoaderUtils.java
= 041a64c32e0296cc799e12d192d4f15bdec83ac5660cc01dc00fd57734a64768
+# Virtual threads: direct JDK 25 API calls instead of reflection
+skywalking/oap-server/server-library/library-util/src/main/java/org/apache/skywalking/oap/server/library/util/VirtualThreads.java
= 79c6a30a0843893bb68f45592f7fde21f3ccfe3e726c3ef8413e397023b766b4
# --- Config-only replacements (added @Setter at class level) ---
skywalking/oap-server/server-receiver-plugin/envoy-metrics-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/envoy/EnvoyMetricReceiverConfig.java
= 2113f0e0c214ec002ba94d8dd06d1ba929c7f54f111266982d1da77c6574c485
diff --git a/oap-libs-for-graalvm/CLAUDE.md b/oap-libs-for-graalvm/CLAUDE.md
index b49bbc7..8de4821 100644
--- a/oap-libs-for-graalvm/CLAUDE.md
+++ b/oap-libs-for-graalvm/CLAUDE.md
@@ -95,11 +95,15 @@ JAVA_HOME=/Users/wusheng/.sdkman/candidates/java/25-graal
make build-distro
|---|---|---|---|
| `ModuleDefine` | `library-module/.../module/ModuleDefine.java` | Added
`prepare()` overload for direct provider wiring | **Yes** |
-### library-util-for-graalvm (0 classes, shade-only)
+### library-util-for-graalvm (1 class)
-No replacement Java sources. Uses shade plugin to exclude
`YamlConfigLoaderUtils`,
-`ResourceUtils`, `FieldsHelper` from upstream JAR. The replacements for these
live
-in `oap-graalvm-server/` (due to 30+ cross-module imports).
+| Replacement Class | Upstream Source | Change | Staleness Tracked |
+|---|---|---|---|
+| `VirtualThreads` | `library-util/.../util/VirtualThreads.java` | Direct JDK
25 API calls instead of reflection | **Yes** |
+
+Also uses shade plugin to exclude `YamlConfigLoaderUtils`, `ResourceUtils`,
+`FieldsHelper` from upstream JAR. The replacements for those live in
+`oap-graalvm-server/` (due to 30+ cross-module imports).
### Config-only replacements (added `@Setter` at class level)
diff --git a/oap-libs-for-graalvm/library-util-for-graalvm/pom.xml
b/oap-libs-for-graalvm/library-util-for-graalvm/pom.xml
index ab03e5b..38ee55e 100644
--- a/oap-libs-for-graalvm/library-util-for-graalvm/pom.xml
+++ b/oap-libs-for-graalvm/library-util-for-graalvm/pom.xml
@@ -61,6 +61,7 @@
<exclude>org/apache/skywalking/oap/server/library/util/ResourceUtils.class</exclude>
<exclude>org/apache/skywalking/oap/server/library/util/FieldsHelper.class</exclude>
<exclude>org/apache/skywalking/oap/server/library/util/FieldsHelper$*.class</exclude>
+
<exclude>org/apache/skywalking/oap/server/library/util/VirtualThreads.class</exclude>
</excludes>
</filter>
</filters>
diff --git
a/oap-libs-for-graalvm/library-util-for-graalvm/src/main/java/org/apache/skywalking/oap/server/library/util/VirtualThreads.java
b/oap-libs-for-graalvm/library-util-for-graalvm/src/main/java/org/apache/skywalking/oap/server/library/util/VirtualThreads.java
new file mode 100644
index 0000000..c51e005
--- /dev/null
+++
b/oap-libs-for-graalvm/library-util-for-graalvm/src/main/java/org/apache/skywalking/oap/server/library/util/VirtualThreads.java
@@ -0,0 +1,97 @@
+/*
+ * 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.oap.server.library.util;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.function.Supplier;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * GraalVM replacement for upstream VirtualThreads.
+ * Original:
skywalking/oap-server/server-library/library-util/src/main/java/.../util/VirtualThreads.java
+ *
+ * <p>Change: Calls JDK 25 virtual thread APIs directly instead of reflection.
+ * This distro targets JDK 25 exclusively, so no reflection needed.
+ * <p>Why: Reflection-based method handles are not needed when the target JDK
is fixed,
+ * and direct calls are GraalVM native-image friendly.
+ */
+@Slf4j
+public final class VirtualThreads {
+
+ static final int MINIMUM_JDK_VERSION = 25;
+ static final String ENV_VIRTUAL_THREADS_ENABLED =
"SW_VIRTUAL_THREADS_ENABLED";
+
+ private static final boolean SUPPORTED;
+
+ static {
+ final String envValue = System.getenv(ENV_VIRTUAL_THREADS_ENABLED);
+ final boolean disabledByEnv = "false".equalsIgnoreCase(envValue);
+
+ if (disabledByEnv) {
+ log.info("Virtual threads disabled by environment variable {}={}",
+ ENV_VIRTUAL_THREADS_ENABLED, envValue);
+ SUPPORTED = false;
+ } else {
+ SUPPORTED = true;
+ log.info("Virtual threads available (JDK {})",
Runtime.version().feature());
+ }
+ }
+
+ private VirtualThreads() {
+ }
+
+ public static boolean isSupported() {
+ return SUPPORTED;
+ }
+
+ public static ExecutorService createExecutor(final String namePrefix,
+ final
Supplier<ExecutorService> platformExecutorSupplier) {
+ return createExecutor(namePrefix, true, platformExecutorSupplier);
+ }
+
+ public static ExecutorService createExecutor(final String namePrefix,
+ final boolean
enableVirtualThreads,
+ final
Supplier<ExecutorService> platformExecutorSupplier) {
+ if (enableVirtualThreads && SUPPORTED) {
+ return createVirtualThreadExecutor(namePrefix);
+ }
+ return platformExecutorSupplier.get();
+ }
+
+ public static ScheduledExecutorService createScheduledExecutor(
+ final String namePrefix,
+ final Supplier<ScheduledExecutorService> platformExecutorSupplier)
{
+ if (SUPPORTED) {
+ final ExecutorService vtExecutor =
createVirtualThreadExecutor(namePrefix);
+ return new VirtualThreadScheduledExecutor(vtExecutor);
+ }
+ return platformExecutorSupplier.get();
+ }
+
+ private static ExecutorService createVirtualThreadExecutor(final String
namePrefix) {
+ final ThreadFactory factory = Thread.ofVirtual()
+ .name("vt:" + namePrefix + "-", 0)
+ .factory();
+ final ExecutorService executor =
Executors.newThreadPerTaskExecutor(factory);
+ log.info("Created virtual-thread-per-task executor [{}]", namePrefix);
+ return executor;
+ }
+}
diff --git
a/oap-libs-for-graalvm/server-core-for-graalvm/src/main/java/org/apache/skywalking/oap/server/core/hierarchy/HierarchyService.java
b/oap-libs-for-graalvm/server-core-for-graalvm/src/main/java/org/apache/skywalking/oap/server/core/hierarchy/HierarchyService.java
index a2c0b16..5d881f9 100644
---
a/oap-libs-for-graalvm/server-core-for-graalvm/src/main/java/org/apache/skywalking/oap/server/core/hierarchy/HierarchyService.java
+++
b/oap-libs-for-graalvm/server-core-for-graalvm/src/main/java/org/apache/skywalking/oap/server/core/hierarchy/HierarchyService.java
@@ -21,6 +21,7 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
+import org.apache.skywalking.oap.server.library.util.VirtualThreads;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.core.CoreModule;
@@ -122,10 +123,16 @@ public class HierarchyService implements
org.apache.skywalking.oap.server.librar
if (!this.isEnableHierarchy) {
return;
}
- Executors.newSingleThreadScheduledExecutor()
- .scheduleWithFixedDelay(
- new
RunnableWithExceptionProtection(this::autoMatchingServiceRelation, t ->
log.error(
- "Scheduled auto matching service hierarchy from
service traffic failure.", t)), 30, 20, TimeUnit.SECONDS);
+ VirtualThreads.createScheduledExecutor(
+ "HierarchyAutoMatching",
+ () -> Executors.newSingleThreadScheduledExecutor(r
-> {
+ final Thread t = new Thread(r,
"HierarchyAutoMatching");
+ t.setDaemon(true);
+ return t;
+ }))
+ .scheduleWithFixedDelay(
+ new
RunnableWithExceptionProtection(this::autoMatchingServiceRelation, t ->
log.error(
+ "Scheduled auto matching service hierarchy from
service traffic failure.", t)), 30, 20, TimeUnit.SECONDS);
}
private void autoMatchingServiceRelation(String upperServiceName,
diff --git a/skywalking b/skywalking
index b537891..a0cec0c 160000
--- a/skywalking
+++ b/skywalking
@@ -1 +1 @@
-Subproject commit b5378919288e4e7992a0a794fa0126ff29a42702
+Subproject commit a0cec0ca237792497d2da0b65757d11f58c3f342