This question is kind of continuation of one previously asked in Preserving parameter/argument names in compiled java classes and the answer is accepted, but the solution seems to be not working.
With ad-hoc built JDK 19 (having exposed Executable.hasRealParameterData()) I take the code
public class Main {
public static void main(String[] args) throws NoSuchMethodException {
Method foo = Main.class.getMethod("foo", String.class, int.class);
System.out.println(foo.hasRealParameterData());
}
public void foo(String parameter1, int parameter2) {}
}
and compile it with
% javac Main.java
Then I run compiled Java class and it prints false into console. This is fine because decompiled Main class looks like
public class Main {
public Main() {}
public static void main(String[] var0) throws NoSuchMethodException {
Method var1 = Main.class.getMethod("foo", String.class, Integer.TYPE);
System.out.println(var1.hasRealParameterData());
}
public void foo(String var1, int var2) {} // parameter names are not 'real'
}
i.e. parameter names are synthetic.
This behaviour is understandable.
Then I take the same Java sources and recompile the class with
javac -g:vars Main.java
I run the same code again and again it prints false to console. This puzzles me, because now the compiled code looks different:
public class Main {
public Main() {}
public static void main(String[] args) throws NoSuchMethodException {
Method foo = Main.class.getMethod("foo", String.class, Integer.TYPE);
System.out.println(foo.hasRealParameterData());
}
public void foo(String parameter1, int parameter2) {} // parameter names are 'real'
}
Same happens if for recompilation I use plain -g flag (generates all auxiliary data).
Now let's stop calling JDK's private API and rely only on the methods available out-of-the-box, e.g. Parameter.isNamePresent() (this one calls Executable.hasRealParameterData() under the hood):
public static void main(String[] args) throws NoSuchMethodException {
Method foo = Main.class.getMethod("foo", String.class, int.class);
Parameter parameter1 = foo.getParameters()[0];
Parameter parameter2 = foo.getParameters()[1];
System.out.println(parameter1.isNamePresent());
System.out.println(parameter2.isNamePresent());
}
public void foo(String parameter1, int parameter2) {}
And again, no matter how I compile the sources, this code prints false false.
The problem here is that Executable.hasRealParameterData() calls native method getParameters0() implemented like:
JVM_ENTRY(jobjectArray, JVM_GetMethodParameters(JNIEnv *env, jobject method))
{
// method is a handle to a java.lang.reflect.Method object
Method* method_ptr = jvm_get_method_common(method);
methodHandle mh (THREAD, method_ptr);
Handle reflected_method (THREAD, JNIHandles::resolve_non_null(method));
const int num_params = mh->method_parameters_length();
if (num_params < 0) {
// A -1 return value from method_parameters_length means there is no
// parameter data. Return null to indicate this to the reflection
// API.
assert(num_params == -1, "num_params should be -1 if it is less than zero");
return (jobjectArray)NULL;
} else {
// Otherwise, we return something up to reflection, even if it is
// a zero-length array. Why? Because in some cases this can
// trigger a MalformedParametersException.
// make sure all the symbols are properly formatted
for (int i = 0; i < num_params; i++) {
MethodParametersElement* params = mh->method_parameters_start();
int index = params[i].name_cp_index;
constantPoolHandle cp(THREAD, mh->constants());
bounds_check(cp, index, CHECK_NULL);
if (0 != index && !mh->constants()->tag_at(index).is_utf8()) {
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
"Wrong type at constant pool index");
}
}
objArrayOop result_oop = oopFactory::new_objArray(vmClasses::reflect_Parameter_klass(), num_params, CHECK_NULL);
objArrayHandle result (THREAD, result_oop);
for (int i = 0; i < num_params; i++) {
MethodParametersElement* params = mh->method_parameters_start();
// For a 0 index, give a NULL symbol
Symbol* sym = 0 != params[i].name_cp_index ?
mh->constants()->symbol_at(params[i].name_cp_index) : NULL;
int flags = params[i].flags;
oop param = Reflection::new_parameter(reflected_method, i, sym,
flags, CHECK_NULL);
result->obj_at_put(i, param);
}
return (jobjectArray)JNIHandles::make_local(THREAD, result());
}
}
JVM_END
From the code I see that null is returned only in case when there's no parameter data. But the data is there, in the compiled class.
So my question is whether this is a bug or am I doing something wrong?
P.S. Parameter.isNamePresent() works unexpectedly even when I run it on conventional, not hacked JDK.
P.P.S. In compiled code I see 'real' parameter names, but if I stop at debug point in IDEA parameter name is suddenly arg0 in Parameter.name field.
As it was pointed out by Daniel Fuchs we need to compile the code with -parameters flag.
https://docs.oracle.com/en/java/javase/18/docs/specs/man/javac.html
Related
I'm trying to create some instrumentation tool. I want to track each object allocation. The simplest idea that came to my mind was to retransform Object constructor as each object calls it (I know that arrays are initialized differently).
I tried use java agent mechanism, but it caused java.lang.instrument.UnmodifiableClassException. Obviously java agent cannot transform Object class at it is unmodifable.
Then I tried use JDI, where my debugged program looked like:
public class First {
public static int value = 1;
public static void main(String... args) throws InterruptedException {
while (true) {
print();
Thread.sleep(1000);
}
}
public static void print() {
System.out.println("Hello" + new Integer(value));
}
}
And debugger did only this:
VirtualMachine vm = new VMAcquirer().connect(8000);
List<ReferenceType> referenceTypes1 = vm.classesByName("java.lang.Object");
ReferenceType object = referenceTypes1.get(0);
if (vm.canRedefineClasses()) {
ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.get("java.lang.Object");
CtConstructor constructor = ctClass.getConstructors()[0];
constructor.insertAfter("First.value += 1;");
HashMap<ReferenceType, byte[]> redefine = new HashMap<>();
redefine.put(object, ctClass.toBytecode());
ctClass.writeFile();
vm.redefineClasses(redefine);
}
vm.resume();
After that target program exits with message:
ERROR: JDWP Transport dt_socket failed to initialize, OUT_OF_MEMORY(110)
Exception: java.lang.StackOverflowError thrown from the UncaughtExceptionHandler in thread "main"
Do I do something wrong here? Is it possible to transform Object class that way?
I know about JVMTI but I wanted avoid C code, so is there any other way that does not require native code?
DISCLAIMER I'm aware of some similar questions already asked here (e.g. Hacking into java.lang.Object: calling custom external class crashes JVM or JDI, Java Byte code instrumentation and Java agents (JWDP, JVMTI)), but they doesn't explain to me everything.
---EDIT---
Transformed Object class looks like this:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package java.lang;
import jdk.internal.HotSpotIntrinsicCandidate;
public class Object {
private static native void registerNatives();
#HotSpotIntrinsicCandidate
public Object() {
Object var2 = null;
++First.value;
}
#HotSpotIntrinsicCandidate
public final native Class<?> getClass();
#HotSpotIntrinsicCandidate
public native int hashCode();
public boolean equals(Object obj) {
return this == obj;
}
#HotSpotIntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;
public String toString() {
return this.getClass().getName() + "#" +
Integer.toHexString(this.hashCode());
}
#HotSpotIntrinsicCandidate
public final native void notify();
#HotSpotIntrinsicCandidate
public final native void notifyAll();
public final void wait() throws InterruptedException {
this.wait(0L);
}
public final native void wait(long var1) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0L) {
throw new IllegalArgumentException("timeout value is negative");
} else if (nanos >= 0 && nanos <= 999999) {
if (nanos > 0) {
++timeout;
}
this.wait(timeout);
} else {
throw new IllegalArgumentException("nanosecond timeout value out of range");
}
}
/** #deprecated */
#Deprecated(
since = "9"
)
protected void finalize() throws Throwable {
}
static {
registerNatives();
}
}
I did also more tests and if I put something like int i = 1; int j = 2 + i; it works.
I also tried modify Integer constructor - this caused another exception:
Exception in thread "main" java.lang.NoClassDefFoundError: First
at java.base/java.lang.Integer.<init>(Integer.java:1075)
at First.print(First.java:13)
at First.main(First.java:7)
Class was successfully transformed, but at runtime there was a problem with linking to the class. I don't know if it is linked somehow. Maybe something similar happens with Object when some internal stuff tries to create new instance.
I was curious about Object var2 = null; line. Javaassist always puts ACONST_NULL bytecode, but it is not the cause of the problem.
---EDIT2---
I tried to transform another Object method. Transformation went succcessfully, but again error occured at runtime:
Exception in thread "main" java.lang.NoClassDefFoundError: First
at java.base/java.lang.Object.toString(Object.java:246)
at First.print(First.java:15)
at First.main(First.java:7)
For me it looks like the real problem is with NoClassDefFoundError. My assumption is it somehow related with classloader system in java (?). Could I somehow avoid such error? I don't know much about classloaders :/
I'm having problems with two void methods. In encouragedVenturesScoring I've followed this answer mocking an arraylist that will be looped in a for loop and haven't mocked the list, but passed a real list and added mocked objects.
Mockito gives me an InvalidUseOfMatchersException on this line
verify(effectList.get(Mockito.anyInt())).execute(playerHandler);
There are lots of questions on SO on this exception , and I think it's because of anyInt(). Anyway I changed it to
verify(effectList.get(0)).execute(playerHandler);
And now it's saying Wanted but not invoked effect.execute(playerHandler)
Actually there were zero interactions with this mock
Is it because I put doNothing ?
doNothing().when(effect).execute(playerHandler);
In my second method militaryStrengthScoring() method is there a way to skip the first chunk of code and just test the if..else condition? What would be the best approach to test this method?
Thank you for your time.
This is the class to be tested
public class EndGameScoringBaseController implements EndGameScoringHandler {
private static final int[] TERRITORIES_REWARD = {0,0,1,4,10,20};
private static final int[] CHARACTERS_REWARD = {1,3,6,10,15,21};
private static final int RESOURCES_RATE = 5;
private static final int FIRST_MILITARY_REWARD = 5;
private static final int SECOND_MILITARY_REWARD = 2;
private PlayerHandler player;
public EndGameScoringBaseController(PlayerHandler player) {
super();
this.player = player;
}
#Override
public void encouragedVenturesScoring() {
for (DevelopmentCard card : player.getPlayer().getPersonalBoard().getVentures()) {
for (Effect e : card.getPermanentEffects())
e.execute(player);
}
}
#Override
public void militaryStrengthScoring(GameController game) {
Set<Integer> points = new HashSet<>();
int myPoints = this.player.getPointsHandler().getMilitaryPoints();
for (PlayerHandler p: game.getPlayers()) {
points.add(p.getPointsHandler().getMilitaryPoints());
}
int[] rank = new int[points.size()];
int j = 0;
for (Integer i : points) {
rank[j] = i;
j++;
}
Arrays.sort(rank);
if (rank[rank.length-1] == myPoints) {
player.getPointsHandler().winMilitaryPoints(FIRST_MILITARY_REWARD);
}
else if (rank[rank.length-2] == myPoints) {
player.getPointsHandler().winVictoryPoints(SECOND_MILITARY_REWARD);
}
}
Tested method for encouragedVenturesScoring
#Test
public void encouragedVenturesScoringTest() {
//given
List<DevelopmentCard> ventureList;
ventureList = Arrays.asList(developmentCard, developmentCard);
when(playerHandler.getPlayer().getPersonalBoard().getVentures()).thenReturn(ventureList);
List<Effect> effectList;
effectList = Arrays.asList(effect, effect);
when(developmentCard.getPermanentEffects()).thenReturn(effectList);
doNothing().when(effect).execute(playerHandler);
//when
endgameController.encouragedVenturesScoring();
//then
verify(effectList.get(Mockito.anyInt())).execute(playerHandler);
}
Incomplete tested method for militaryStrengthScoring
#Test
public void militaryStrengthScoringTest() {
//given
when(playerHandler.getPointsHandler().getMilitaryPoints()).thenReturn(4);
doNothing().when(playerHandler.getPointsHandler()).winMilitaryPoints(FIRST_MILITARY_REWARD);
//when
endgameController.militaryStrengthScoring(gameController);
//then
/../
}
You're right that this is the problem:
verify(effectList.get(Mockito.anyInt())).execute(playerHandler);
Mockito only allows for calls like any() and anyInt() to stand in for parameters to the mock themselves, due to the internal implementation of matchers.
/* OK */ when(yourMock.yourMethod(anyInt())).thenReturn(42);
/* BAD */ when(yourList.get(anyInt()).yourMethod(0)).thenReturn(42);
/* OK */ verify(yourMock).yourMethod(anyInt());
/* BAD */ verify(yourList.get(anyInt())).yourMethod(0);
The failure with get(0) is likely an actual failure, and may be related to the fact that your encouragedVenturesScoringTest is actually not calling encouragedVenturesScoring, it's calling influencedCharactersScoring. If this continues to give you trouble after fixing that error, in ways related to Mockito, please edit your question.
You can only verify mock objects created by Mockito.
But effectList is a "real" list. Therefore Mockito knows nothing about that object. Thus any attempt to verify that list must fail.
If you want to verify that object - then you have to mock it!
Of course, this means that you have specify all calls that will go to the mocked list.
I'm looking for an API which generates me source code that would generate objects equal to the ones I passed to the library.
public static void main(String[] args) {
int[] arr = new int[3];
arr[0] = 3;
arr[1] = 4;
arr[2] = 5;
// looking for this one
MagicCode.generateCode(arr);
}
Should generate
int[] arr = new int[3];
arr[0] = 3;
arr[1] = 4;
arr[2] = 5;
or
int[] arr = new int[] { 3, 4, 5 };
So I want to pass an Object and get the Java Source Code that would create an object equal to my initial Object.
That should not only work for primitive types but for my own objects too:
public static void main(String[] args) {
Condition condition = new Condition();
condition.setNumber(2);
// looking for this one
MagicCode.generateCode(condition);
}
Should generate
Condition c1 = new Condition();
c1.setNumber(2);
as a String which can then be pasted to a Java Source file.
EDIT
I don't want to bypass the compiler.
I'm about to rewrite a component that isn't tested well. So there are about 1000 test cases to be written. The functionality is basically input/output. I have 1000 input Strings and want to test that after rewriting the component it behaves exactly the same.
Therefore I would like to have each object implement #toString() so that it creates Java source to create itself. Then I can pass my 1000 Strings and let the current implementation write the test case to ensure the behaviour of the component.
Code generation is fun! You can achieve what you need by using reflection, sadly, there is no MagicCode implemented already.
You need to use the introspection to read what kind of object and create it according.
You can use the Eclipse JDT API to create classes.
Generating a compilation unit
The easiest way to programmatically generate a compilation unit is to use IPackageFragment.createCompilationUnit. You specify the name and contents of the compilation unit. The compilation unit is created inside the package and the new ICompilationUnit is returned.
From the docs, there is a example snippet.
So you basically will introspect to see what kind of object is and what is their fields and current values. Then you will use this API do create a corresponding AST. Your example might look like this.
public class CodeGenerator {
public static void main(String[] args) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Foo foobar = new Foo();
Bar bar = new Bar();
bar.setSomeValue(555d);
foobar.setBar(bar);
foobar.setPrimitiveDouble(23);
foobar.setValue("Hello World!");
CodeGenerator codeGenerator = new CodeGenerator();
String generatedCode = codeGenerator.generateCode(foobar);
System.out.println(generatedCode);
}
int counter = 0;
private String createVariableName(String clazzName) {
return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, clazzName + getCurrentCounter());
}
public String generateCode(AST ast, List statements, Object object) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
String clazzName = object.getClass().getSimpleName();
String variableName = createVariableName(clazzName);
VariableDeclarationFragment newVariable = ast.newVariableDeclarationFragment();
newVariable.setName(ast.newSimpleName(variableName)); // Or clazzName.toCamelCase()
ClassInstanceCreation newInstance = ast.newClassInstanceCreation();
newInstance.setType(ast.newSimpleType(ast.newSimpleName(clazzName)));
newVariable.setInitializer(newInstance);
VariableDeclarationStatement newObjectStatement = ast.newVariableDeclarationStatement(newVariable);
newObjectStatement.setType(ast.newSimpleType(ast.newSimpleName(clazzName)));
statements.add(newObjectStatement);
BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass());
for (PropertyDescriptor propertyDesc : beanInfo.getPropertyDescriptors()) {
String propertyName = propertyDesc.getName();
if (!shouldIgnore(propertyName)) {
MethodInvocation setterInvocation = ast.newMethodInvocation();
SimpleName setterName = ast.newSimpleName(propertyDesc.getWriteMethod().getName());
setterInvocation.setName(setterName);
Object invoked = propertyDesc.getReadMethod().invoke(object);
if (invoked == null) {
continue;
}
if (Primitives.isWrapperType(invoked.getClass())) {
if (Number.class.isAssignableFrom(invoked.getClass())) {
setterInvocation.arguments().add(ast.newNumberLiteral(invoked.toString()));
}
// TODO: Booleans
} else {
if (invoked instanceof String) {
StringLiteral newStringLiteral = ast.newStringLiteral();
newStringLiteral.setLiteralValue(invoked.toString());
setterInvocation.arguments().add(newStringLiteral);
} else {
String newObjectVariable = generateCode(ast, statements, invoked);
SimpleName newSimpleName = ast.newSimpleName(newObjectVariable);
setterInvocation.arguments().add(newSimpleName);
}
}
SimpleName newSimpleName = ast.newSimpleName(variableName);
setterInvocation.setExpression(newSimpleName);
ExpressionStatement setterStatement = ast.newExpressionStatement(setterInvocation);
statements.add(setterStatement);
}
}
return variableName;
}
public String generateCode(Object object) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
resetCounter();
AST ast = AST.newAST(AST.JLS3);
Block block = ast.newBlock();
generateCode(ast, block.statements(), object);
return block.toString();
}
private int getCurrentCounter() {
return counter++;
}
private void resetCounter() {
counter = 0;
}
private boolean shouldIgnore(String propertyName) {
return "class".equals(propertyName);
}
}
The dependencies I used:
<dependency>
<groupId>org.eclipse.tycho</groupId>
<artifactId>org.eclipse.jdt.core</artifactId>
<version>3.9.1.v20130905-0837</version>
</dependency>
<dependency>
<groupId>org.eclipse.core</groupId>
<artifactId>runtime</artifactId>
<version>3.9.100-v20131218-1515</version>
</dependency>
<dependency>
<groupId>org.eclipse.birt.runtime</groupId>
<artifactId>org.eclipse.core.resources</artifactId>
<version>3.8.101.v20130717-0806</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
This is what the output looks like :
Foo foo0=new Foo();
Bar bar1=new Bar();
bar1.setSomeValue(555.0);
foo0.setBar(bar1);
foo0.setPrimitiveDouble(23.0);
foo0.setValue("Hello World!");
Here is the Foo and Bar class declaration:
public class Bar {
private double someValue;
public double getSomeValue() {
return someValue;
}
public void setSomeValue(double someValue) {
this.someValue = someValue;
}
}
public class Foo {
private String value;
private double primitiveDouble;
private Bar bar;
public Bar getBar() {
return bar;
}
public double getPrimitiveDouble() {
return primitiveDouble;
}
public String getValue() {
return value;
}
public void setBar(Bar bar) {
this.bar = bar;
}
public void setPrimitiveDouble(double primitiveDouble) {
this.primitiveDouble = primitiveDouble;
}
public void setValue(String value) {
this.value = value;
}
}
I added this to a github repository as requested.
You don't need the generated source code for testing. If all of your classes have toString methods that represent the whole relevant internal state of your objects, you can still automatically generate the test cases: they will compare strings with strings.
There are lots of ways to automatically generate good toString methods, for example Intellij Idea offers 9 templates.
If you have a String that contains a source code and wish to compile it at run time, there is the Java Compiler API for this purpose
Im beginner JAVA developer. Here is a method:
private Method getSomething()
{
for (Method m : getClass().getDeclaredMethods())
{
return m;
}
return notFound;
}
private void notFound()
{
throw new Exception();
}
it doesnt matter what it does - if it finds something, then returns a Method - if not, the notFound() method itself should be returned. So the hot spot is at the return notFound; line: if I use return notFound(); then it returns its value, not the method itself. I want something like a reference/pointer. So getSomething() returns something what can be called, and if the returned method is used wrong, it should trigger that Exception - so its not an option to replace return notFound; with throw new Exception(); !
Or the 2nd option is to create a lambda method....
You need to call
this.getClass().getMethod("notFound")
to get the notFound method of the current/this object's class.
So just do this:
return this.getClass().getMethod("notFound");
More details here:
Class.getMethod
EDIT:
You can retrieve i.e. get and call private methods too via reflection.
Here is an example.
import java.lang.reflect.Method;
public class Test001 {
public static void main(String[] args) throws Exception {
Test002 obj = new Test002();
Method m = obj.getClass().getDeclaredMethod("testMethod", int.class);
m.setAccessible(true);
m.invoke(obj, 10);
m.invoke(obj, 20);
System.out.println(m.getName());
}
}
class Test002 {
private void testMethod(int x){
System.out.println("Hello there: " + x);
}
}
You need to use reflection to achieve this:
http://docs.oracle.com/javase/tutorial/reflect/
e.g. to get all methods of a given class:
Class aClass = ...//obtain class object
Method[] methods = aClass.getMethods();
I'm getting an error that I really can't explain when trying to compile my Java code:
error: constructor MinimaxThread in class MinimaxThread cannot be applied to given types;
MinimaxThread mmt = new MinimaxThread(board.clone(), 2, true);
^
required: no arguments
found: MCBoard,int,boolean
reason: actual and formal argument lists differ in length
The error makes no sense, as I have a constructor that takes an MCBoard, int, and boolean:
public class MinimaxThread implements Runnable {
public MCBoard board;
public int depth;
public HashMap<Tuple, Integer> moveEvals;
boolean cont = true;
boolean verbose = false;
public MinimaxThread(MCBoard board, int initialDepth, boolean verbose) {
this.board = board;
depth = initialDepth;
moveEvals = new HashMap<Tuple, Integer>();
for (Tuple t : board.legalMoves) {
moveEvals.put(t, new Integer(0));
}
this.verbose = verbose;
}
It's an overloaded constructor (there is one with just MCBoard and one with MCBoard and int), but I don't see how that would matter. Any ideas? Here's the calling code:
public static void testMinimax(){
MCBoard board = new MCBoard();
board.move(5,0);
board.move(4,0);
board.move(5,2);
MinimaxThread mmt = new MinimaxThread(board.clone(), 2, true);
mmt.run();
}
edit: board.clone() is overridden:
public MCBoard clone() {
// irrelevant code removed
return new MCBoard(gridClone, turn, legalMovesClone, moveListClone);
}
edit #2: Here is my git repository, for reproducibility:
https://github.com/cowpig/MagneticCave
EDIT: Now that you've given us your github URL, we can see what MinimaxThread really looks like - at least in the latest pushed code:
public class MinimaxThread extends Thread {
public MCBoard board;
public int depth;
}
Yup, I can see why the compiler would complain at that constructor call...
EDIT: Before we knew that MCBoard.clone() was overridden, the answer below made sense. Now, however, I can see no reason why the compiler should complain. Indeed, using the code you've given (but ignoring the actual implementation, which is irrelevant) it all compiles fine:
MinimaxThread.java:
public class MinimaxThread implements Runnable {
public MinimaxThread(MCBoard board, int initialDepth, boolean verbose) {
}
public void run() {
}
}
MCBoard.java:
public class MCBoard {
public MCBoard clone() {
return null;
}
}
Test.java:
public class Test {
public static void main(String[] args) throws Exception {
MCBoard board = new MCBoard();
MinimaxThread mmt = new MinimaxThread(board.clone(), 2, true);
}
}
So I suspect you're not building the code you've presented. Try to build the code above, and if that works, see if you can figure out the difference between that and your actual code.
Original answer
Presumably the compiler "thinks" that board.clone() returns Object, because that's what's declared by Object.clone(). So you need to cast the result to MCBoard:
MinimaxThread mmt = new MinimaxThread((MCBoard) board.clone(), 2, true);
Alternatively, you could override clone() within MCBoard, declaring that it returns MCBoard rather than Object.