I created a simple test that runs under terracotta (it is NOT sharing anything) that has a similar structure as the real application but stripped down. It seems like a class loader issue (terracotta 3.5.0); does it have anything to do with this code from BootJarTool.java?
Code:
private final void addInstrumentedJavaUtilConcurrentFutureTask() {
if (!Vm.isJDK15Compliant()) { return; }
final Map instrumentedContext = new HashMap();
TransparencyClassSpec spec = this.configHelper.getOrCreateSpec("java.util.concurrent.FutureTask");
spec.setHonorTransient(true);
spec.setCallConstructorOnLoad(true);
spec.markPreInstrumented();
changeClassName("java.util.concurrent.FutureTaskTC", "java.util.concurrent.FutureTaskTC",
"java.util.concurrent.FutureTask", instrumentedContext, true);
this.configHelper.addWriteAutolock("* java.util.concurrent.FutureTask$Sync.*(..)");
spec = this.configHelper.getOrCreateSpec("java.util.concurrent.FutureTask$Sync");
spec.setHonorTransient(true);
spec.markPreInstrumented();
spec.addDistributedMethodCall("managedInnerCancel", "()V", true);
changeClassName("java.util.concurrent.FutureTaskTC$Sync", "java.util.concurrent.FutureTaskTC",
"java.util.concurrent.FutureTask", instrumentedContext, true);
}
My test code. If you run it as a regular java app, it logs
"java.lang.Exception: test exception
"... exiting"
If you start it as a terracotta app (note that there is NOTHING shared), you get
"java.lang.ClassCastException: java.util.concurrent.FutureTask cannot be cast to java.util.concurrent.RunnableFuture
... exiting"
The line that throws class cast exception is:
"for (RunnableFuture<T> future : submittedTasks) { ..."
Code:
package com.acme.test;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class TestThreadPoolExecutor {
public static final TestThreadPoolExecutor testPool =
new TestThreadPoolExecutor( 4, 4, 0L,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
private ThreadPoolExecutor delegate;
TestThreadPoolExecutor( int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue ) {
delegate = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue );
}
public <T> Future<T> submit(Runnable task, T result) {
return delegate.submit(task, result);
}
public void execute(Runnable task) {
delegate.execute(task);
}
public BlockingQueue<Runnable> getQueue() {
return delegate.getQueue();
}
public List<Runnable> shutdownNow() {
return delegate.shutdownNow();
}
public static void main(String args[]) {
Tasks<String> tasks = new Tasks<String>();
int nofTasks = 10;
final Random random = new Random();
for(int counter = 0; counter < nofTasks; ++counter) {
tasks.start(new Runnable(){
@Override
public void run() {
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}}, "task " + Integer.toString(counter));
}
try {
tasks.waitForAll();
} catch(ClassCastException cce) {
System.err.println(cce);
} catch(RuntimeException re) {
System.err.println(re.getCause());
} finally {
System.out.println("... exiting");
testPool.shutdownNow();
}
}
public static final class Tasks<T> {
private final List<RunnableFuture<T>> submittedTasks = new ArrayList<RunnableFuture<T>>();
private final TestThreadPoolExecutor exec = testPool;
private boolean doneSubmitting;
volatile boolean forceException = true;
public void start(Runnable task, final T result) {
if (doneSubmitting) {
throw new IllegalStateException(
"Tasks.start() not allowed to be called after Tasks.waitForAll()");
}
addTask((FutureTask<T>) exec.submit(task, result));
}
private void addTask(RunnableFuture<T> wrappedTask) {
submittedTasks.add(wrappedTask);
}
public List<T> waitForAll() {
doneSubmitting = true;
List<T> results = new ArrayList<T>(submittedTasks.size());
boolean done = false;
try {
// Go through the whole list to gather the results.
for (Future<T> task : submittedTasks) {
try {
results.add(task.get());
if (forceException) {
throw new Exception("test exception");
}
} catch (ExecutionException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw ((RuntimeException) t);
} else {
throw new RuntimeException(t);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
done = true;
} finally {
if (!done) {
for (RunnableFuture<T> future : submittedTasks) {
future.cancel(false);
}
}
}
return results;
}
}
}
The configuration is the following (adding RunnableFuture to the additional boot jar classes does not change anything):
Code:
<?xml version="1.0" encoding="UTF-8"?>
<con:tc-config xmlns:con="http://www.terracotta.org/config">
<servers>
<server host="%i" name="localhost">
<dso-port bind="0.0.0.0">9510</dso-port>
<jmx-port bind="0.0.0.0">9520</jmx-port>
<data>terracotta/server-data</data>
<logs>terracotta/server-logs</logs>
<statistics>terracotta/cluster-statistics</statistics>
</server>
</servers>
<clients>
<logs>terracotta/client-logs</logs>
</clients>
<application>
<dso>
<instrumented-classes/>
<additional-boot-jar-classes>
<include>java.util.concurrent.RunnableFuture</include>
</additional-boot-jar-classes>
</dso>
</application>
</con:tc-config>
Environment (to make it short, JDK 1.6.0_25, 64b, Windows):
Code:
awt.toolkit: sun.awt.windows.WToolkit
com.sun.management.jmxremote:
com.sun.management.jmxremote.authenticate: false
file.encoding: Cp1252
file.encoding.pkg: sun.io
file.separator: \
h2.maxFileRetry: 8
java.awt.graphicsenv: sun.awt.Win32GraphicsEnvironment
java.awt.printerjob: sun.awt.windows.WPrinterJob
java.class.path: C:\eclipse\plugins\org.terracotta.dso_3.5.0.r17406_v20110326\lib\resources;C:\eclipse\plugins\org.terracotta.dso_3.5.0.r17406_v20110326\lib\tc.jar
java.class.version: 50.0
java.endorsed.dirs: C:\Java\jdk1.6.0_25\jre\lib\endorsed
java.ext.dirs: C:\Java\jdk1.6.0_25\jre\lib\ext;C:\windows\Sun\Java\lib\ext
java.home: C:\Java\jdk1.6.0_25\jre
java.io.tmpdir: C:\Users\ADMINI~1\AppData\Local\Temp\
java.library.path: C:\Java\jdk1.6.0_25\bin;.;C:\windows\Sun\Java\bin;C:\windows\system32;C:\windows;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\windows\system32;C:\windows;C:\windows\System32\Wbem;C:\windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\WIDCOMM\Bluetooth Software\;C:\Program Files\WIDCOMM\Bluetooth Software\syswow64;C:\Program Files (x86)\MySQL\MySQL Server 5.1\bin;C:\Program Files\Microsoft Windows Performance Toolkit\;C:\Java\jdk1.6.0_25\bin
java.rmi.server.randomIDs: true
java.runtime.name: Java(TM) SE Runtime Environment
java.runtime.version: 1.6.0_25-b06
java.specification.name: Java Platform API Specification
java.specification.vendor: Sun Microsystems Inc.
java.specification.version: 1.6
java.vendor: Sun Microsystems Inc.
java.vendor.url: http://java.sun.com/
java.vendor.url.bug: http://java.sun.com/cgi-bin/bugreport.cgi
java.version: 1.6.0_25
java.vm.info: mixed mode
java.vm.name: Java HotSpot(TM) 64-Bit Server VM
java.vm.specification.name: Java Virtual Machine Specification
java.vm.specification.vendor: Sun Microsystems Inc.
java.vm.specification.version: 1.0
java.vm.vendor: Sun Microsystems Inc.
java.vm.version: 20.0-b11
line.separator:
os.arch: amd64
os.name: Windows 7
os.version: 6.1
path.separator: ;
sun.arch.data.model: 64
sun.boot.class.path: C:\Java\jdk1.6.0_25\jre\lib\resources.jar;C:\Java\jdk1.6.0_25\jre\lib\rt.jar;C:\Java\jdk1.6.0_25\jre\lib\sunrsasign.jar;C:\Java\jdk1.6.0_25\jre\lib\jsse.jar;C:\Java\jdk1.6.0_25\jre\lib\jce.jar;C:\Java\jdk1.6.0_25\jre\lib\charsets.jar;C:\Java\jdk1.6.0_25\jre\lib\modules\jdk.boot.jar;C:\Java\jdk1.6.0_25\jre\classes
sun.boot.library.path: C:\Java\jdk1.6.0_25\jre\bin
sun.cpu.endian: little
sun.cpu.isalist: amd64
sun.desktop: windows
sun.io.unicode.encoding: UnicodeLittle
sun.java.command: com.tc.server.TCServerMain
sun.java.launcher: SUN_STANDARD
sun.jnu.encoding: Cp1252
sun.management.compiler: HotSpot 64-Bit Tiered Compilers
sun.os.patch.level: Service Pack 1
tc.config: C:tmp\tc-config.xml
tc.install-root: C:\eclipse\plugins\org.terracotta.dso_3.5.0.r17406_v20110326
tc.server.name: localhost
user.country: US
user.dir: C:\Users\Administrator\test
user.home: C:\Users\Administrator
user.language: en
user.name: Administrator
user.timezone: America/Los_Angeles
user.variant: