Skip to content

Commit

Permalink
kie-issue#1738: customize ForkJoinPool to explicitly inherit the cont…
Browse files Browse the repository at this point in the history
…ext ClassLoader from the parent thread (#6211)

* kie-issue#1738: customize ForkJoinPool to explicitly inherit the context ClassLoader from the parent thread

* kie-issue#1738: ops, forgot the header :)
  • Loading branch information
porcelli authored Jan 7, 2025
1 parent dee09fd commit 84eb420
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinWorkerThread;
import java.util.function.Supplier;

import org.drools.base.RuleBase;
Expand Down Expand Up @@ -500,10 +501,11 @@ protected PackageRegistryManager getPackageRegistryManager() {
}

public static class ForkJoinPoolHolder {
public static final ForkJoinPool COMPILER_POOL = new ForkJoinPool(); // avoid common pool
public static final ForkJoinPool COMPILER_POOL = new ForkJoinPool(Math.min(32767, Runtime.getRuntime().availableProcessors()), pool -> new ForkJoinWorkerThread(pool) {{
setContextClassLoader(Thread.currentThread().getContextClassLoader());
}}, null, false); // avoid common pool
}


public boolean filterAccepts(ResourceChange.Type type, String namespace, String name) {
return assetFilter == null || !AssetFilter.Action.DO_NOTHING.equals(assetFilter.accept(type, namespace, name));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**
* 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.drools.compiler.builder.impl;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.TimeUnit;

import static org.junit.jupiter.api.Assertions.assertSame;

public class KnowledgeBuilderImplCompilerFJPoolTest {

private ClassLoader originalClassLoader;
private ClassLoader customClassLoader;

@BeforeEach
void setUp() {
// Save the original classloader
originalClassLoader = Thread.currentThread().getContextClassLoader();

// Create a custom classloader for testing
customClassLoader = new ClassLoader(ClassLoader.getSystemClassLoader()) {};
Thread.currentThread().setContextClassLoader(customClassLoader);
}

@AfterEach
void tearDown() {
// Restore original classloader
Thread.currentThread().setContextClassLoader(originalClassLoader);
}

private static class ClassLoaderCheckTask extends RecursiveAction {
private final List<ClassLoader> results;
private final int index;

public ClassLoaderCheckTask(List<ClassLoader> results, int index) {
this.results = results;
this.index = index;
}

@Override
protected void compute() {
results.set(index, Thread.currentThread().getContextClassLoader());
}
}

@Test
void testCompilerPoolClassLoader() throws Exception {
int numTasks = 5;
List<ClassLoader> results = new ArrayList<>(numTasks);
for (int i = 0; i < numTasks; i++) {
results.add(null);
}

// Submit tasks to the COMPILER_POOL
for (int i = 0; i < numTasks; i++) {
KnowledgeBuilderImpl.ForkJoinPoolHolder.COMPILER_POOL.submit(new ClassLoaderCheckTask(results, i));
}

// Wait for completion
KnowledgeBuilderImpl.ForkJoinPoolHolder.COMPILER_POOL.awaitQuiescence(1, TimeUnit.SECONDS);

// Verify all worker threads have the expected classloader
for (ClassLoader workerClassLoader : results) {
assertSame(
customClassLoader,
workerClassLoader,
"Worker thread should have inherited the custom classloader"
);
}
}
}

0 comments on commit 84eb420

Please sign in to comment.