aboutsummaryrefslogtreecommitdiffstats
path: root/dcevm
diff options
context:
space:
mode:
authorIvan Dubrov <idubrov@guidewire.com>2014-04-24 19:22:17 -0700
committerIvan Dubrov <idubrov@guidewire.com>2014-04-24 19:22:17 -0700
commit070f0932b7f5f901551d42850b1c105a080cc40b (patch)
treecfa0d0be6e34ae108180d071b77c98b8994ebb8c /dcevm
parentf3d1c500f2cb30e2203df86844b378ea1b6bc53d (diff)
downloaddcevm-070f0932b7f5f901551d42850b1c105a080cc40b.tar.gz
dcevm-070f0932b7f5f901551d42850b1c105a080cc40b.zip
Adding Java 7 patch, support running tests on Java 7
Diffstat (limited to 'dcevm')
-rw-r--r--dcevm/src/main/java/org/dcevm/ClassRedefinitionPolicy.java40
-rw-r--r--dcevm/src/main/java/org/dcevm/HotSwapTool.java233
-rw-r--r--dcevm/src/main/java/org/dcevm/InstrumentationRedefiner.java54
-rw-r--r--dcevm/src/main/java/org/dcevm/JDIRedefiner.java153
-rw-r--r--dcevm/src/main/java/org/dcevm/Redefiner.java37
-rw-r--r--dcevm/src/main/java/org/dcevm/TestClassAdapter.java101
-rw-r--r--dcevm/src/test/java/org/dcevm/test/LightTestSuite.java49
-rw-r--r--dcevm/src/test/java/org/dcevm/test/TestUtil.java86
-rw-r--r--dcevm/src/test/java/org/dcevm/test/body/ArrayTest.java98
-rw-r--r--dcevm/src/test/java/org/dcevm/test/body/BodyTestSuite.java53
-rw-r--r--dcevm/src/test/java/org/dcevm/test/body/ClassRenamingTestCase.java68
-rw-r--r--dcevm/src/test/java/org/dcevm/test/body/EMCPTest.java219
-rw-r--r--dcevm/src/test/java/org/dcevm/test/body/FacTest.java103
-rw-r--r--dcevm/src/test/java/org/dcevm/test/body/FibTest.java110
-rw-r--r--dcevm/src/test/java/org/dcevm/test/body/MultipleThreadsTest.java207
-rw-r--r--dcevm/src/test/java/org/dcevm/test/body/OldActivationTest.java158
-rw-r--r--dcevm/src/test/java/org/dcevm/test/body/RedefinePrivateMethodTest.java96
-rw-r--r--dcevm/src/test/java/org/dcevm/test/body/RefactorActiveMethodTest.java96
-rw-r--r--dcevm/src/test/java/org/dcevm/test/body/SimpleStaticTest.java128
-rw-r--r--dcevm/src/test/java/org/dcevm/test/body/StaticTest.java300
-rw-r--r--dcevm/src/test/java/org/dcevm/test/body/StressTest.java82
-rw-r--r--dcevm/src/test/java/org/dcevm/test/eval/AddingInterfaceTest.java122
-rw-r--r--dcevm/src/test/java/org/dcevm/test/eval/EvalTestSuite.java42
-rw-r--r--dcevm/src/test/java/org/dcevm/test/eval/FractionTest.java256
-rw-r--r--dcevm/src/test/java/org/dcevm/test/eval/GeometryScenario.java207
-rw-r--r--dcevm/src/test/java/org/dcevm/test/fields/ComplexFieldTest.java104
-rw-r--r--dcevm/src/test/java/org/dcevm/test/fields/EnumTest.java70
-rw-r--r--dcevm/src/test/java/org/dcevm/test/fields/FieldAlignmentTest.java63
-rw-r--r--dcevm/src/test/java/org/dcevm/test/fields/FieldChangedOrderTest.java184
-rw-r--r--dcevm/src/test/java/org/dcevm/test/fields/FieldModificationTest.java278
-rw-r--r--dcevm/src/test/java/org/dcevm/test/fields/FieldsTestSuite.java49
-rw-r--r--dcevm/src/test/java/org/dcevm/test/fields/ObjectStressTest.java122
-rw-r--r--dcevm/src/test/java/org/dcevm/test/fields/RedefinePrivateFieldTest.java97
-rw-r--r--dcevm/src/test/java/org/dcevm/test/fields/StringFieldTest.java78
-rw-r--r--dcevm/src/test/java/org/dcevm/test/fields/YieldTest.java123
-rw-r--r--dcevm/src/test/java/org/dcevm/test/methods/AddMethodTest.java166
-rw-r--r--dcevm/src/test/java/org/dcevm/test/methods/AnnotationTest.java121
-rw-r--r--dcevm/src/test/java/org/dcevm/test/methods/ClassObjectHashcodeTest.java92
-rw-r--r--dcevm/src/test/java/org/dcevm/test/methods/ClassObjectSynchronizationTest.java79
-rw-r--r--dcevm/src/test/java/org/dcevm/test/methods/ClassReflectionTest.java160
-rw-r--r--dcevm/src/test/java/org/dcevm/test/methods/DeleteActiveMethodTest.java159
-rw-r--r--dcevm/src/test/java/org/dcevm/test/methods/MethodReflectionTest.java152
-rw-r--r--dcevm/src/test/java/org/dcevm/test/methods/MethodsTestSuite.java49
-rw-r--r--dcevm/src/test/java/org/dcevm/test/methods/OverrideMethodTest.java247
-rw-r--r--dcevm/src/test/java/org/dcevm/test/methods/SingleClassReflectionTest.java88
-rw-r--r--dcevm/src/test/java/org/dcevm/test/methods/SingleClassTest.java123
-rw-r--r--dcevm/src/test/java/org/dcevm/test/structural/AnonymousClassInMethodTest.java67
-rw-r--r--dcevm/src/test/java/org/dcevm/test/structural/InterfaceTest.java144
-rw-r--r--dcevm/src/test/java/org/dcevm/test/structural/RedefineClassClassTest.java71
-rw-r--r--dcevm/src/test/java/org/dcevm/test/structural/RedefineObjectClassTest.java149
-rw-r--r--dcevm/src/test/java/org/dcevm/test/structural/StructuralTestSuite.java45
-rw-r--r--dcevm/src/test/java/org/dcevm/test/structural/ThisTypeChange.java124
-rw-r--r--dcevm/src/test/java/org/dcevm/test/util/HotSwapTestHelper.java81
-rw-r--r--dcevm/src/test/java8/org/dcevm/test/methods/DefaultMethodsTest.java110
-rw-r--r--dcevm/src/test/java8/org/dcevm/test/util/HotSwapTestHelper.java81
55 files changed, 6574 insertions, 0 deletions
diff --git a/dcevm/src/main/java/org/dcevm/ClassRedefinitionPolicy.java b/dcevm/src/main/java/org/dcevm/ClassRedefinitionPolicy.java
new file mode 100644
index 00000000..32571863
--- /dev/null
+++ b/dcevm/src/main/java/org/dcevm/ClassRedefinitionPolicy.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package org.dcevm;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * @author Kerstin Breiteneder
+ */
+@Retention(value = RetentionPolicy.RUNTIME)
+public @interface ClassRedefinitionPolicy {
+
+ // Default value if no alias is set.
+ public final static class NoClass {
+ }
+
+ Class<?> alias() default NoClass.class;
+}
diff --git a/dcevm/src/main/java/org/dcevm/HotSwapTool.java b/dcevm/src/main/java/org/dcevm/HotSwapTool.java
new file mode 100644
index 00000000..b622cba9
--- /dev/null
+++ b/dcevm/src/main/java/org/dcevm/HotSwapTool.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package org.dcevm;
+
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Type;
+
+import java.io.*;
+import java.lang.instrument.UnmodifiableClassException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+/**
+ * @author Thomas Wuerthinger
+ * @author Kerstin Breiteneder
+ * @author Christoph Wimberger
+ * @author Ivan Dubrov
+ */
+public class HotSwapTool {
+
+ /**
+ * Prefix for the version number in the class name. The class bytes are modified that this string including
+ * the following number is removed. This means that e.g. A___2 is treated as A anywhere in the source code. This is introduced
+ * to make the IDE not complain about multiple defined classes.
+ */
+ public static final String IDENTIFIER = "___";
+ private static final String CLASS_FILE_SUFFIX = ".class";
+ private static Map<Class<?>, Integer> currentVersion = new Hashtable<Class<?>, Integer>();
+ private static Redefiner redefiner;
+ private static int redefinitionCount;
+ private static long totalTime;
+
+ static {
+ try {
+ //redefiner = new JDIRedefiner(4000);
+ redefiner = new InstrumentationRedefiner();
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Returns the current version of the inner classes of a specified outer class.
+ *
+ * @param baseClass the outer class whose version is queried
+ * @return the version of the inner classes of the specified outer class
+ */
+ public static int getCurrentVersion(Class<?> baseClass) {
+ if (!currentVersion.containsKey(baseClass)) {
+ currentVersion.put(baseClass, 0);
+ }
+ return currentVersion.get(baseClass);
+ }
+
+ /**
+ * Performs an explicit shutdown and disconnects from the VM.
+ */
+ public static void shutdown() throws IOException {
+ redefiner.close();
+ redefiner = null;
+ }
+
+ private static Map<Class<?>, byte[]> buildRedefinitionMap(Map<String, File> classes) throws IOException, ClassNotFoundException {
+ // Collect rename rules
+ // Also, makes sure all classes are loaded in the VM, before they are redefined
+ final Map<String, String> typeMappings = new HashMap<String, String>();
+ for (String name : classes.keySet()) {
+ Class<?> clazz = Class.forName(name); // FIXME: classloader?
+ ClassRedefinitionPolicy policy = clazz.getAnnotation(ClassRedefinitionPolicy.class);
+ Class<?> replacement = (policy != null && policy.alias() != ClassRedefinitionPolicy.NoClass.class) ?
+ policy.alias() : clazz;
+ typeMappings.put(Type.getInternalName(clazz), stripVersion(Type.getInternalName(replacement)));
+
+ }
+
+ Map<Class<?>, byte[]> classesMap = new HashMap<Class<?>, byte[]>();
+ for (File file : classes.values()) {
+ loadAdaptedClass(file, typeMappings, classesMap);
+ }
+ return classesMap;
+ }
+
+ private static void loadAdaptedClass(File file, Map<String, String> typeMappnigs, Map<Class<?>, byte[]> result) throws IOException, ClassNotFoundException {
+
+ ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
+ TestClassAdapter adapter = new TestClassAdapter(writer, typeMappnigs);
+
+ InputStream in = new FileInputStream(file);
+ try {
+ new ClassReader(in).accept(adapter, ClassReader.EXPAND_FRAMES);
+ } finally {
+ try {
+ in.close();
+ } catch (IOException e) {
+ // Ignore.
+ }
+ }
+ byte[] bytes = writer.toByteArray();
+ String className = adapter.getClassName().replace('/', '.');
+ result.put(Class.forName(className), bytes); // FIXME: ClassLoader...
+ }
+
+ /**
+ * Redefines all inner classes of a outer class to a specified version. Inner classes who do not have a particular
+ * representation for a version remain unchanged.
+ *
+ * @param outerClass the outer class whose inner classes should be redefined
+ * @param versionNumber the target version number
+ */
+ public static void toVersion(Class<?> outerClass, int versionNumber) {
+ assert versionNumber >= 0;
+
+ if (versionNumber == getCurrentVersion(outerClass)) {
+ // Nothing to do!
+ return;
+ }
+
+ Map<String, File> files = findClassesWithVersion(outerClass, versionNumber);
+
+ try {
+ Map<Class<?>, byte[]> map = buildRedefinitionMap(files);
+
+ long startTime = System.currentTimeMillis();
+ redefiner.redefineClasses(map);
+ long curTime = System.currentTimeMillis() - startTime;
+ totalTime += curTime;
+ redefinitionCount++;
+
+ } catch (UnmodifiableClassException e) {
+ throw new UnsupportedOperationException(e);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Cannot redefine classes", e);
+ } catch (IOException e) {
+ throw new RuntimeException("Cannot redefine classes", e);
+ }
+
+ setCurrentVersion(outerClass, versionNumber);
+ }
+
+ private static Map<String, File> findClassesWithVersion(Class<?> baseClass, int version) {
+ Map<String, File> classes = new HashMap<String, File>();
+
+ String packageName = baseClass.getPackage().getName().replace('.', '/');
+ URL url = baseClass.getClassLoader().getResource(packageName);
+ if (url == null) {
+ throw new IllegalArgumentException("Cannot find URL corresponding to the package '" + packageName + "'");
+ }
+ File folder = new File(url.getFile());
+ for (File f : folder.listFiles(IsClassFile.INSTANCE)) {
+ String fileName = f.getName();
+ String simpleName = f.getName().substring(0, f.getName().length() - CLASS_FILE_SUFFIX.length());
+ String name = baseClass.getPackage().getName() + '.' + simpleName;
+
+ if (isInnerClass(name, baseClass) && parseClassVersion(fileName) == version) {
+ classes.put(name, f);
+ }
+ }
+ return classes;
+ }
+
+ private enum IsClassFile implements FilenameFilter {
+ INSTANCE;
+
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.endsWith(CLASS_FILE_SUFFIX);
+ }
+ }
+
+ private static boolean isInnerClass(String name, Class<?> baseClass) {
+ return name.startsWith(baseClass.getName() + "$");
+ }
+
+ private static void setCurrentVersion(Class<?> baseClass, int value) {
+ currentVersion.put(baseClass, value);
+ }
+
+ /**
+ * Parse version of the class from the class name. Classes are named in the form of [Name]___[Version]
+ */
+ private static int parseClassVersion(String name) {
+ int index = name.indexOf(IDENTIFIER);
+ if (index == -1) {
+ return 0;
+ }
+ return Integer.valueOf(name.substring(index + IDENTIFIER.length(), name.length() - CLASS_FILE_SUFFIX.length()));
+ }
+
+ private static String stripVersion(String className) {
+ int index = className.indexOf(IDENTIFIER);
+ if (index == -1) {
+ return className;
+ }
+ return className.substring(0, index);
+ }
+
+ public static void resetTimings() {
+ redefinitionCount = 0;
+ totalTime = 0;
+ }
+
+ public static int getRedefinitionCount() {
+ return redefinitionCount;
+ }
+
+ public static long getTotalTime() {
+ return totalTime;
+ }
+}
diff --git a/dcevm/src/main/java/org/dcevm/InstrumentationRedefiner.java b/dcevm/src/main/java/org/dcevm/InstrumentationRedefiner.java
new file mode 100644
index 00000000..247fbb2e
--- /dev/null
+++ b/dcevm/src/main/java/org/dcevm/InstrumentationRedefiner.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package org.dcevm;
+
+
+import org.dcevm.agent.InstrumentationAgent;
+
+import java.io.IOException;
+import java.lang.instrument.ClassDefinition;
+import java.lang.instrument.Instrumentation;
+import java.lang.instrument.UnmodifiableClassException;
+import java.util.Map;
+
+public class InstrumentationRedefiner implements Redefiner {
+ public void redefineClasses(Map<Class<?>, byte[]> classes) throws ClassNotFoundException, UnmodifiableClassException {
+ Instrumentation instrumentation = InstrumentationAgent.INSTRUMENTATION;
+ if (instrumentation == null) {
+ throw new IllegalStateException("Instrumentation agent is not properly installed!");
+ }
+
+ ClassDefinition[] definitions = new ClassDefinition[classes.size()];
+ int i = 0;
+ for (Map.Entry<Class<?>, byte[]> entry : classes.entrySet()) {
+ definitions[i++] = new ClassDefinition(entry.getKey(), entry.getValue());
+ }
+ instrumentation.redefineClasses(definitions);
+ }
+
+ @Override
+ public void close() throws IOException {
+ // Do nothing.
+ }
+}
diff --git a/dcevm/src/main/java/org/dcevm/JDIRedefiner.java b/dcevm/src/main/java/org/dcevm/JDIRedefiner.java
new file mode 100644
index 00000000..6fc742d4
--- /dev/null
+++ b/dcevm/src/main/java/org/dcevm/JDIRedefiner.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package org.dcevm;
+
+import com.sun.jdi.Bootstrap;
+import com.sun.jdi.ReferenceType;
+import com.sun.jdi.VirtualMachine;
+import com.sun.jdi.VirtualMachineManager;
+import com.sun.jdi.connect.AttachingConnector;
+import com.sun.jdi.connect.Connector.Argument;
+import com.sun.jdi.connect.IllegalConnectorArgumentsException;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Utility class for performing class redefinition using JDI.
+ * </li>
+ * </ul>
+ *
+ * @author Thomas Wuerthinger
+ * @author Kerstin Breiteneder
+ * @author Christoph Wimberger
+ *
+ */
+public class JDIRedefiner implements Redefiner {
+
+ private static final String PORT_ARGUMENT_NAME = "port";
+ private static final String TRANSPORT_NAME = "dt_socket";
+
+ private VirtualMachine vm;
+
+
+ /** Port at which to connect to the agent of the VM. **/
+ public static final int PORT = 4000;
+
+ public JDIRedefiner(int port) throws IOException {
+ vm = connect(port);
+ }
+
+ @Override
+ public void close() throws IOException {
+ disconnect();
+ }
+
+ private VirtualMachine connect(int port) throws IOException {
+ VirtualMachineManager manager = Bootstrap.virtualMachineManager();
+
+ // Find appropiate connector
+ List<AttachingConnector> connectors = manager.attachingConnectors();
+ AttachingConnector chosenConnector = null;
+ for (AttachingConnector c : connectors) {
+ if (c.transport().name().equals(TRANSPORT_NAME)) {
+ chosenConnector = c;
+ break;
+ }
+ }
+ if (chosenConnector == null) {
+ throw new IllegalStateException("Could not find socket connector");
+ }
+
+ // Set port argument
+ AttachingConnector connector = chosenConnector;
+ Map<String, Argument> defaults = connector.defaultArguments();
+ Argument arg = defaults.get(PORT_ARGUMENT_NAME);
+ if (arg == null) {
+ throw new IllegalStateException("Could not find port argument");
+ }
+ arg.setValue(Integer.toString(port));
+
+ // Attach
+ try {
+ System.out.println("Connector arguments: " + defaults);
+ return connector.attach(defaults);
+ } catch (IllegalConnectorArgumentsException e) {
+ throw new IllegalArgumentException("Illegal connector arguments", e);
+ }
+ }
+
+ public void disconnect() {
+ if (vm != null) {
+ vm.dispose();
+ vm = null;
+ }
+ }
+
+ public void redefineClasses(Map<Class<?>, byte[]> classes) {
+ refreshAllClasses();
+ List<ReferenceType> references = vm.allClasses();
+
+ Map<ReferenceType, byte[]> map = new HashMap<ReferenceType, byte[]>(classes.size());
+ for (Map.Entry<Class<?>, byte[]> entry : classes.entrySet()) {
+ map.put(findReference(references, entry.getKey().getName()), entry.getValue());
+ }
+ vm.redefineClasses(map);
+ }
+
+ /**
+ * Call this method before calling allClasses() in order to refresh the JDI state of loaded classes.
+ * This is necessary because the JDI map of all loaded classes is only updated based on events received over JDWP (network connection)
+ * and therefore it is not necessarily up-to-date with the real state within the VM.
+ */
+ private void refreshAllClasses() {
+ try {
+ Field f = vm.getClass().getDeclaredField("retrievedAllTypes");
+ f.setAccessible(true);
+ f.set(vm, false);
+ } catch (IllegalArgumentException ex) {
+ Logger.getLogger(HotSwapTool.class.getName()).log(Level.SEVERE, null, ex);
+ } catch (IllegalAccessException ex) {
+ Logger.getLogger(HotSwapTool.class.getName()).log(Level.SEVERE, null, ex);
+ } catch (NoSuchFieldException ex) {
+ Logger.getLogger(HotSwapTool.class.getName()).log(Level.SEVERE, null, ex);
+ } catch (SecurityException ex) {
+ Logger.getLogger(HotSwapTool.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ private static ReferenceType findReference(List<ReferenceType> list, String name) {
+ for (ReferenceType ref : list) {
+ if (ref.name().equals(name)) {
+ return ref;
+ }
+ }
+ throw new IllegalArgumentException("Cannot find corresponding reference for class name '" + name + "'" );
+ }
+}
diff --git a/dcevm/src/main/java/org/dcevm/Redefiner.java b/dcevm/src/main/java/org/dcevm/Redefiner.java
new file mode 100644
index 00000000..cd183fe3
--- /dev/null
+++ b/dcevm/src/main/java/org/dcevm/Redefiner.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package org.dcevm;
+
+import java.io.Closeable;
+import java.lang.instrument.UnmodifiableClassException;
+import java.util.Map;
+
+/**
+ * Interface to the class redefinition implementation (JDI-based, Instrumenattion API based)
+ *
+ * @author Ivan Dubrov
+ */
+public interface Redefiner extends Closeable {
+ void redefineClasses(Map<Class<?>, byte[]> classes) throws ClassNotFoundException, UnmodifiableClassException;
+}
diff --git a/dcevm/src/main/java/org/dcevm/TestClassAdapter.java b/dcevm/src/main/java/org/dcevm/TestClassAdapter.java
new file mode 100644
index 00000000..bd4b2daf
--- /dev/null
+++ b/dcevm/src/main/java/org/dcevm/TestClassAdapter.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package org.dcevm;
+
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.commons.Remapper;
+import org.objectweb.asm.commons.RemappingClassAdapter;
+import org.objectweb.asm.commons.RemappingMethodAdapter;
+
+import java.util.Map;
+
+/**
+ * @author Ivan Dubrov
+ */
+public class TestClassAdapter extends RemappingClassAdapter {
+ /**
+ * This suffix is automatically removed from the method.
+ */
+ private final static String METHOD_SUFFIX = "___";
+
+ private boolean isObject;
+
+ public TestClassAdapter(ClassVisitor cv, final Map<String, String> typeMappings) {
+ super(cv, new Remapper() {
+ @Override
+ public String map(String type) {
+ return typeMappings.containsKey(type) ? typeMappings.get(type) : type;
+ }
+ });
+ }
+
+ @Override
+ public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+ // For java/lang/Object redefinition
+ String newName = remapper.mapType(name);
+ if (newName.equals("java/lang/Object")) {
+ superName = null;
+ isObject = true;
+ }
+ super.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
+ return super.visitMethod(access, stripMethodSuffix(name), desc, signature, exceptions);
+ }
+
+ /**
+ * Get renamed class name.
+ *
+ * @return
+ */
+ public String getClassName() {
+ return remapper.mapType(className);
+ }
+
+ protected MethodVisitor createRemappingMethodAdapter(
+ int access,
+ String newDesc,
+ MethodVisitor mv)
+ {
+ return new RemappingMethodAdapter(access, newDesc, mv, remapper) {
+ @Override
+ public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+ if (name.equals("<init>") && isObject && owner.equals("java/lang/Object")) {
+ return;
+ }
+
+ super.visitMethodInsn(opcode, owner, stripMethodSuffix(name), desc);
+ }
+ };
+ }
+
+ private static String stripMethodSuffix(String name) {
+ int pos = name.indexOf(METHOD_SUFFIX);
+ return (pos != -1) ? name.substring(0, pos) : name;
+ }
+}
+
diff --git a/dcevm/src/test/java/org/dcevm/test/LightTestSuite.java b/dcevm/src/test/java/org/dcevm/test/LightTestSuite.java
new file mode 100644
index 00000000..b5a2af02
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/LightTestSuite.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test;
+
+import org.dcevm.test.body.BodyTestSuite;
+import org.dcevm.test.eval.EvalTestSuite;
+import org.dcevm.test.fields.FieldsTestSuite;
+import org.dcevm.test.methods.MethodsTestSuite;
+import org.dcevm.test.structural.StructuralTestSuite;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * Summarizes all available test suites.
+ *
+ * @author Thomas Wuerthinger
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ BodyTestSuite.class,
+ EvalTestSuite.class,
+ MethodsTestSuite.class,
+ FieldsTestSuite.class,
+ StructuralTestSuite.class
+})
+public class LightTestSuite {
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/TestUtil.java b/dcevm/src/test/java/org/dcevm/test/TestUtil.java
new file mode 100644
index 00000000..7876dac5
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/TestUtil.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test;
+
+import junit.framework.Assert;
+import org.dcevm.HotSwapTool;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+
+/**
+ * Utility methods for unit testing.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class TestUtil {
+
+ public static final boolean LIGHT = true;
+
+ public static int assertException(Class exceptionClass, Runnable run) {
+
+ try {
+ run.run();
+ } catch (Throwable t) {
+ if (t.getClass().equals(exceptionClass)) {
+ return t.getStackTrace()[0].getLineNumber();
+ }
+ Assert.assertTrue("An exception of type " + t.getClass().getSimpleName() + " instead of " + exceptionClass.getSimpleName() + " has been thrown!", false);
+ }
+
+ Assert.assertTrue("No exception has been thrown!", false);
+ return -1;
+ }
+
+ public static int assertUnsupportedWithLight(Runnable run) {
+ if (TestUtil.LIGHT) {
+ return assertUnsupported(run);
+ }
+ run.run();
+ return -1;
+ }
+
+ public static int assertUnsupported(Runnable run) {
+ return assertException(UnsupportedOperationException.class, run);
+ }
+
+ public static void assertUnsupportedToVersion(final Class clazz, final int version) {
+ TestUtil.assertUnsupported(new Runnable() {
+ @Override
+ public void run() {
+ HotSwapTool.toVersion(clazz, version);
+ }
+ });
+ }
+
+ public static void assertUnsupportedToVersionWithLight(final Class clazz, final int version) {
+ TestUtil.assertUnsupportedWithLight(new Runnable() {
+ @Override
+ public void run() {
+ HotSwapTool.toVersion(clazz, version);
+ }
+ });
+ }
+
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/body/ArrayTest.java b/dcevm/src/test/java/org/dcevm/test/body/ArrayTest.java
new file mode 100644
index 00000000..d82f5010
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/body/ArrayTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.body;
+
+import org.dcevm.test.TestUtil;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.lang.reflect.Array;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Ivan Dubrov
+ */
+public class ArrayTest {
+
+ public class A {
+ }
+
+ public class A___1 {
+ }
+
+ public class B extends A {
+ }
+
+ public class B___1 extends A {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testArray() {
+ Object[] arr = new A[] { new A(), new A() };
+ A[] arr2 = new B[] { new B(), new B() };
+ A[][] arr3 = new B[10][];
+
+ __toVersion__(1);
+
+ assertTrue(arr instanceof A[]);
+ assertTrue(arr instanceof Object[]);
+ assertEquals(arr.getClass(), Array.newInstance(A.class, 0).getClass());
+
+ assertTrue(arr2 instanceof B[]);
+ assertTrue(arr2 instanceof A[]);
+ assertTrue(arr2 instanceof Object[]);
+ assertEquals(arr2.getClass(), Array.newInstance(B.class, 0).getClass());
+
+ assertTrue(arr3 instanceof B[][]);
+ assertTrue(arr3 instanceof A[][]);
+ assertTrue(arr3 instanceof Object[][]);
+ assertEquals(arr3.getClass(), Array.newInstance(B[].class, 0).getClass());
+
+ __toVersion__(0);
+
+ assertTrue(arr instanceof A[]);
+ assertTrue(arr instanceof Object[]);
+ assertEquals(arr.getClass(), Array.newInstance(A.class, 0).getClass());
+
+ assertTrue(arr2 instanceof B[]);
+ assertTrue(arr2 instanceof A[]);
+ assertTrue(arr2 instanceof Object[]);
+ assertEquals(arr2.getClass(), Array.newInstance(B.class, 0).getClass());
+
+ assertTrue(arr3 instanceof B[][]);
+ assertTrue(arr3 instanceof A[][]);
+ assertTrue(arr3 instanceof Object[][]);
+ assertEquals(arr3.getClass(), Array.newInstance(B[].class, 0).getClass());
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/body/BodyTestSuite.java b/dcevm/src/test/java/org/dcevm/test/body/BodyTestSuite.java
new file mode 100644
index 00000000..37426aab
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/body/BodyTestSuite.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.body;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * Class redefinition tests that swap only method bodies and change nothing else. This test cases should also
+ * run with the current version of HotSpot.
+ *
+ * @author Thomas Wuerthinger
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses(
+ {
+ StaticTest.class,
+ SimpleStaticTest.class,
+ MultipleThreadsTest.class,
+ OldActivationTest.class,
+ RefactorActiveMethodTest.class,
+ StressTest.class,
+ FacTest.class,
+ FibTest.class,
+ RedefinePrivateMethodTest.class,
+ ClassRenamingTestCase.class,
+ EMCPTest.class,
+ ArrayTest.class
+ })
+public class BodyTestSuite {
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/body/ClassRenamingTestCase.java b/dcevm/src/test/java/org/dcevm/test/body/ClassRenamingTestCase.java
new file mode 100644
index 00000000..84488815
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/body/ClassRenamingTestCase.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package org.dcevm.test.body;
+
+import org.dcevm.ClassRedefinitionPolicy;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Kerstin Breiteneder
+ * @author Christoph Wimberger
+ */
+public class ClassRenamingTestCase {
+
+ public static class B {
+
+ public int a() {
+ return 1;
+ }
+ }
+
+ @ClassRedefinitionPolicy(alias = B.class)
+ public static class A___1 {
+
+ public int a() {
+ return 2;
+ }
+ }
+
+ @Test
+ public void testRenaming() {
+ __toVersion__(0);
+
+ B b = new B();
+ assertEquals(1, b.a());
+
+ __toVersion__(1);
+
+ assertEquals(2, b.a());
+
+ __toVersion__(0);
+
+ assertEquals(1, b.a());
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/body/EMCPTest.java b/dcevm/src/test/java/org/dcevm/test/body/EMCPTest.java
new file mode 100644
index 00000000..0d28d6fe
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/body/EMCPTest.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package org.dcevm.test.body;
+
+import org.dcevm.test.TestUtil;
+import org.junit.Test;
+
+import java.io.PrintStream;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * EMCP (Equivalent modulo Constant Pool) tests.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class EMCPTest {
+
+ public static class A {
+
+ public static int EMCPReturn() {
+ change();
+ PrintStream s = System.out;
+ return 1;
+ }
+ }
+
+ public static class B {
+
+ public static int b() {
+ change();
+ throw new RuntimeException();
+ }
+ }
+
+ public static class C {
+
+ public static int c() {
+ changeAndThrow();
+ return 0;
+ }
+ }
+
+ public static class D {
+
+ private static int value = 1;
+
+ public static int EMCPReturn() {
+ change3();
+ return value;
+ }
+ }
+
+ public static class A___1 {
+
+ public static int EMCPReturn() {
+ change();
+ PrintStream s = System.out;
+ return 1;
+ }
+ }
+
+ public static class B___1 {
+
+ public static int b() {
+ change();
+ throw new RuntimeException();
+ }
+ }
+
+ public static class C___1 {
+
+ public static int c() {
+ changeAndThrow();
+ return 0;
+ }
+ }
+
+ public static class D___1 {
+ private static int value = 1;
+
+ public static int EMCPReturn() {
+ change3();
+ return value;
+ }
+ }
+
+ public static class D___2 {
+ private static int value = 1;
+
+ public static int EMCPReturn() {
+ change3();
+ return value;
+ }
+ }
+
+ public static class D___3 {
+ private static int value = 1;
+
+ public static int EMCPReturn() {
+ change3();
+ return value;
+ }
+ }
+
+ public static void change() {
+
+ __toVersion__(1);
+ }
+
+ public static void change3() {
+
+ __toVersion__(1);
+ __toVersion__(2);
+ __toVersion__(3);
+ }
+
+ public static void changeAndThrow() {
+
+ __toVersion__(1);
+
+ throw new RuntimeException();
+ }
+
+
+ @Test
+ public void testEMCPReturn() {
+ __toVersion__(0);
+
+ assertEquals(1, A.EMCPReturn());
+
+ __toVersion__(0);
+
+ assertEquals(1, A.EMCPReturn());
+
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testEMCPMultiChangeReturn() {
+ __toVersion__(0);
+
+ assertEquals(1, D.EMCPReturn());
+
+ __toVersion__(0);
+
+ assertEquals(1, D.EMCPReturn());
+
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testEMCPException() {
+ __toVersion__(0);
+
+ TestUtil.assertException(RuntimeException.class, new Runnable() {
+ @Override
+ public void run() {
+ B.b();
+ }
+ });
+
+ __toVersion__(0);
+
+ TestUtil.assertException(RuntimeException.class, new Runnable() {
+ @Override
+ public void run() {
+ B.b();
+ }
+ });
+
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testEMCPExceptionInCallee() {
+ __toVersion__(0);
+
+ TestUtil.assertException(RuntimeException.class, new Runnable() {
+ @Override
+ public void run() {
+ C.c();
+ }
+ });
+
+ __toVersion__(0);
+
+ TestUtil.assertException(RuntimeException.class, new Runnable() {
+ @Override
+ public void run() {
+ C.c();
+ }
+ });
+
+ __toVersion__(0);
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/body/FacTest.java b/dcevm/src/test/java/org/dcevm/test/body/FacTest.java
new file mode 100644
index 00000000..832ea7a8
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/body/FacTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.body;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Recursive implementation of the factorial function using class redefinition.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class FacTest {
+
+ public static abstract class Base {
+
+ protected int calc() {
+ return calc(__version__());
+ }
+
+ public int calcAt(int version) {
+ __toVersion__(version);
+ int result = calc();
+ __toVersion__(0);
+ return result;
+ }
+
+ protected int calc(int version) {
+ return calc();
+ }
+ }
+
+ public static class Factorial extends Base {
+
+ @Override
+ protected int calc(int n) {
+ return n * calcAt(n - 1);
+ }
+ }
+
+ public static class Factorial___1 extends Base {
+
+ @Override
+ protected int calc() {
+ return 1;
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testFac() {
+
+ assert __version__() == 0;
+ Factorial f = new Factorial();
+
+ assertEquals(1, f.calcAt(1));
+
+ assert __version__() == 0;
+ assertEquals(2, f.calcAt(2));
+
+ assert __version__() == 0;
+ assertEquals(6, f.calcAt(3));
+
+ assert __version__() == 0;
+ assertEquals(24, f.calcAt(4));
+
+ assert __version__() == 0;
+ assertEquals(120, f.calcAt(5));
+
+ assert __version__() == 0;
+ assertEquals(479001600, f.calcAt(12));
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/body/FibTest.java b/dcevm/src/test/java/org/dcevm/test/body/FibTest.java
new file mode 100644
index 00000000..c95f2de5
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/body/FibTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.body;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Recursive implementation of the fibonacci function using class redefinition.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class FibTest {
+
+ public static abstract class Base {
+
+ protected int calc() {
+ return calc(__version__());
+ }
+
+ public int calcAt(int version) {
+ __toVersion__(version);
+ int result = calc();
+ __toVersion__(0);
+ return result;
+ }
+
+ protected int calc(int version) {
+ return calc();
+ }
+ }
+
+ public static class Fib extends Base {
+
+ @Override
+ protected int calc(int n) {
+ return calcAt(n - 1) + calcAt(n - 2);
+ }
+ }
+
+ public static class Fib___1 extends Base {
+
+ @Override
+ protected int calc() {
+ return 1;
+ }
+ }
+
+ public static class Fib___2 extends Base {
+
+ @Override
+ protected int calc() {
+ return 2;
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testFib() {
+
+ // 0 1 2 3 4 5
+ // 1 1 2 3 5 8
+ assert __version__() == 0;
+ Fib f = new Fib();
+
+ assertEquals(1, f.calcAt(1));
+
+ assert __version__() == 0;
+ assertEquals(2, f.calcAt(2));
+
+ assert __version__() == 0;
+ assertEquals(3, f.calcAt(3));
+
+ assert __version__() == 0;
+ assertEquals(5, f.calcAt(4));
+
+ assert __version__() == 0;
+ assertEquals(8, f.calcAt(5));
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/body/MultipleThreadsTest.java b/dcevm/src/test/java/org/dcevm/test/body/MultipleThreadsTest.java
new file mode 100644
index 00000000..4966a2fc
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/body/MultipleThreadsTest.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.body;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Class for testing redefining methods of classes that extend the Thread class. In the test setup the run method
+ * calls the doit method in a loop until this methods returns false.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class MultipleThreadsTest {
+
+ public static final int COUNT = 10;
+
+ // Version 0
+ public static class A extends Thread {
+
+ private int value;
+ private int value2;
+ private boolean flag = false;
+
+ @Override
+ public void run() {
+ while (doit()) {
+ flag = false;
+ }
+ }
+
+ public boolean doit() {
+ if (flag) {
+ throw new RuntimeException("Must not reach here");
+ }
+ flag = true;
+ try {
+ Thread.sleep(1);
+ } catch (InterruptedException e) {
+ }
+
+ value++;
+ return true;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public int getValue2() {
+ return value2;
+ }
+ }
+
+ // Version 1
+ public static class A___1 extends Thread {
+
+ private int value;
+ private int value2;
+ private boolean flag = false;
+
+ @Override
+ public void run() {
+ while (doit()) {
+ flag = false;
+ }
+ }
+
+ public boolean doit() {
+ if (flag) {
+ throw new RuntimeException("Must not reach here");
+ }
+ flag = true;
+ try {
+ Thread.sleep(1);
+ } catch (InterruptedException e) {
+ }
+
+ value2++;
+ return true;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public int getValue2() {
+ return value2;
+ }
+ }
+
+ // Version 2
+ public static class A___2 extends Thread {
+
+ private int value;
+ private int value2;
+ private boolean flag = false;
+
+ @Override
+ public void run() {
+ while (doit()) {
+ flag = false;
+ }
+ }
+
+ public boolean doit() {
+ return false;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public int getValue2() {
+ return value2;
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testOneThread() {
+ test(1);
+ }
+
+ @Test
+ public void testThreads() {
+ test(COUNT);
+ }
+
+ private void test(int count) {
+
+ assert __version__() == 0;
+
+ A[] arr = new A[count];
+ for (int i = 0; i < count; i++) {
+ arr[i] = new A();
+ arr[i].start();
+ }
+
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ }
+
+ for (int i = 0; i < count; i++) {
+ //assertTrue(arr[i].getValue() > 0);
+ }
+
+ __toVersion__(1);
+
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ }
+
+ for (int i = 0; i < count; i++) {
+ assertTrue(arr[i].getValue2() > 0);
+ }
+
+ __toVersion__(2);
+
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ }
+
+
+ for (int i = 0; i < count; i++) {
+ assertFalse(arr[i].isAlive());
+ }
+
+ __toVersion__(0);
+
+
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/body/OldActivationTest.java b/dcevm/src/test/java/org/dcevm/test/body/OldActivationTest.java
new file mode 100644
index 00000000..3ad7f400
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/body/OldActivationTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.body;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Stress test for the number of old activations on the stack. In the test setup 10 different versions of the method A.value will be on the stack.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class OldActivationTest {
+
+ // Version 0
+ public static class A {
+
+ public int value() {
+ __toVersion__(1);
+ return 1 + this.value();
+ }
+ }
+
+ // Version 1
+ public static class A___1 {
+
+ public int value() {
+ __toVersion__(2);
+ return 2 + this.value();
+ }
+ }
+
+ // Version 2
+ public static class A___2 {
+
+ public int value() {
+ __toVersion__(3);
+ return 3 + this.value();
+ }
+ }
+
+ // Version 3
+ public static class A___3 {
+
+ public int value() {
+ __toVersion__(4);
+ return 4 + this.value();
+ }
+ }
+
+ // Version 4
+ public static class A___4 {
+
+ public int value() {
+ __toVersion__(5);
+ return 5 + this.value();
+ }
+ }
+
+ // Version 5
+ public static class A___5 {
+
+ public int value() {
+ __toVersion__(6);
+ return 6 + this.value();
+ }
+ }
+
+ // Version 6
+ public static class A___6 {
+
+ public int value() {
+ __toVersion__(7);
+ return 7 + this.value();
+ }
+ }
+
+ // Version 7
+ public static class A___7 {
+
+ public int value() {
+ __toVersion__(8);
+ return 8 + this.value();
+ }
+ }
+
+ // Version 8
+ public static class A___8 {
+
+ public int value() {
+ __toVersion__(9);
+ return 9 + this.value();
+ }
+ }
+
+ // Version 9
+ public static class A___9 {
+
+ public int value() {
+ __toVersion__(0);
+ return 10;
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testOldActivationTest() {
+
+ assert __version__() == 0;
+
+ A a = new A();
+
+ assertEquals(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10, a.value());
+ assert __version__() == 0;
+
+ __toVersion__(1);
+ assertEquals(2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10, a.value());
+ assert __version__() == 0;
+
+ __toVersion__(8);
+ assertEquals(9 + 10, a.value());
+ assert __version__() == 0;
+
+ __toVersion__(4);
+ assertEquals(5 + 6 + 7 + 8 + 9 + 10, a.value());
+ assert __version__() == 0;
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/body/RedefinePrivateMethodTest.java b/dcevm/src/test/java/org/dcevm/test/body/RedefinePrivateMethodTest.java
new file mode 100644
index 00000000..935907fa
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/body/RedefinePrivateMethodTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.body;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests redefinition of a class such that old code still accesses a redefined private method.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class RedefinePrivateMethodTest {
+
+ // Version 0
+ public static class A {
+
+ public int foo() {
+ int result = bar();
+ __toVersion__(1);
+ result += bar();
+ return result;
+ }
+
+ private int bar() {
+ return 1;
+ }
+ }
+
+ // Version 1
+ public static class A___1 {
+
+ public int foo() {
+ return -1;
+ }
+
+ private int bar() {
+ return 2;
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testRedefinePrivateMethod() {
+
+ assert __version__() == 0;
+
+ A a = new A();
+
+ assertEquals(3, a.foo());
+
+ assert __version__() == 1;
+
+ assertEquals(-1, a.foo());
+
+ __toVersion__(0);
+
+ assertEquals(3, a.foo());
+
+ assert __version__() == 1;
+
+ assertEquals(-1, a.foo());
+
+ __toVersion__(0);
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/body/RefactorActiveMethodTest.java b/dcevm/src/test/java/org/dcevm/test/body/RefactorActiveMethodTest.java
new file mode 100644
index 00000000..4dd433ce
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/body/RefactorActiveMethodTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.body;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Thomas Wuerthinger
+ */
+public class RefactorActiveMethodTest {
+
+ // Version 0
+ public static class A {
+
+ public int value() {
+ __toVersion__(1);
+ return 5;
+ }
+
+ public int secondValue() {
+ return 1;
+ }
+ }
+
+ // Version 1
+ public static class A___1 {
+
+ public int value() {
+ return secondValue() * 2;
+ }
+
+ public int secondValue() {
+ return 2;
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testActiveMethodReplacement() {
+
+ assert __version__() == 0;
+
+ A a = new A();
+
+ assertEquals(5, a.value());
+
+ assert __version__() == 1;
+
+ assertEquals(2, a.secondValue());
+ assertEquals(4, a.value());
+ assertEquals(2, a.secondValue());
+
+ assert __version__() == 1;
+
+ __toVersion__(0);
+
+ assertEquals(1, a.secondValue());
+ assertEquals(5, a.value());
+ assertEquals(4, a.value());
+
+ __toVersion__(0);
+
+ assertEquals(1, a.secondValue());
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/body/SimpleStaticTest.java b/dcevm/src/test/java/org/dcevm/test/body/SimpleStaticTest.java
new file mode 100644
index 00000000..a456381d
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/body/SimpleStaticTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.body;
+
+import org.dcevm.test.TestUtil;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Thomas Wuerthinger
+ */
+public class SimpleStaticTest {
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+
+ // E and Helper must be loaded and initialized
+ E e = new E();
+ Helper h = new Helper();
+ }
+
+ // Version 0
+
+ public static class Helper {
+ public static int getIntegerField() {
+ return E.integerField;
+ }
+
+ public static void setIntegerField(int x) {
+ E.integerField = x;
+ }
+
+ public static int getFinalIntegerField() {
+ return E.finalIntegerField;
+ }
+ }
+
+ public static class E {
+ public static int integerField = 10;
+
+ public static E self = new E();
+
+ // javac will generate "ConstantValue" attribute for this field!
+ public static final int finalIntegerField = 7;
+ }
+
+ public static class E___1 {
+ public static E___1 self = new E___1();
+ }
+
+ // Version 1
+ public static class E___2 {
+ public static int integerField = 10;
+
+ // javac will generate "ConstantValue" attribute for this field!
+ public static final int finalIntegerField = 7;
+ }
+
+ @Test
+ public void testSimpleNewStaticField() {
+
+ assert __version__() == 0;
+
+ __toVersion__(1);
+
+ TestUtil.assertException(NoSuchFieldError.class, new Runnable() {
+ @Override
+ public void run() {
+ Helper.getIntegerField();
+ }
+ });
+
+ __toVersion__(2);
+
+ assertEquals(0, Helper.getIntegerField());
+ assertEquals(7, Helper.getFinalIntegerField());
+ Helper.setIntegerField(1000);
+ assertEquals(1000, Helper.getIntegerField());
+
+ __toVersion__(1);
+
+ TestUtil.assertException(NoSuchFieldError.class, new Runnable() {
+ @Override
+ public void run() {
+ Helper.getIntegerField();
+ }
+ });
+
+ __toVersion__(2);
+
+ assertEquals(0, Helper.getIntegerField());
+ assertEquals(7, Helper.getFinalIntegerField());
+ Helper.setIntegerField(1000);
+ assertEquals(1000, Helper.getIntegerField());
+
+ __toVersion__(0);
+
+ assertEquals(7, Helper.getFinalIntegerField());
+ assertEquals(1000, Helper.getIntegerField());
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/body/StaticTest.java b/dcevm/src/test/java/org/dcevm/test/body/StaticTest.java
new file mode 100644
index 00000000..b4369b77
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/body/StaticTest.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.body;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static junit.framework.Assert.assertNull;
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Thomas Wuerthinger
+ */
+public class StaticTest {
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ // Version 0
+
+
+ public static class Helper {
+ public static int getAdditionalField() {
+ return -1;
+ }
+
+ public static void setAdditionalField(int x) {
+
+ }
+ }
+
+ public static class A {
+
+ public static int value() {
+ return 1;
+ }
+ }
+
+ public static class B {
+
+ public static int value() {
+ return 2;
+ }
+ }
+
+ public static class C {
+ static {
+ System.out.println("Static initializer of C");
+ }
+
+ public static int value = 5;
+ }
+
+ public static class D {
+ public static List objectField = new ArrayList();
+ public static int[] arrayField = new int[10];
+ public static int integerField = 5;
+ public static char characterField = 6;
+ public static short shortField = 7;
+ public static double doubleField = 1.0;
+ public static float floatField = 2.0f;
+ public static long longField = 8;
+ public static boolean booleanField = true;
+ }
+
+ // Version 1
+ public static class A___1 {
+
+ public static int value() {
+ return B.value() * 2;
+ }
+ }
+
+ // Version 2
+ public static class B___2 {
+
+ public static int value() {
+ return 3;
+ }
+ }
+
+ // Version 3
+ public static class A___3 {
+
+ public static int value() {
+ return 5;
+ }
+ }
+
+ public static class B___3 {
+
+ public static int value() {
+ return A.value() * 2;
+ }
+ }
+
+ // Version 4
+ public static class C___4 {
+
+ static {
+ System.out.println("Static initializer of C-4");
+ }
+
+ public static int value = 6;
+ }
+
+ public static class Helper___5 {
+ public static int getAdditionalField() {
+ return D___5.additionalField;
+ }
+
+ public static void setAdditionalField(int x) {
+ D___5.additionalField = x;
+ }
+ }
+
+ public static class D___5 {
+ public static int additionalField;
+
+ public static List objectField;
+ public static long longField;
+ public static short shortField = 10;
+ public static float floatField;
+ public static int[] arrayField;
+ public static int integerField;
+ public static char characterField;
+ public static double doubleField;
+ public static boolean booleanField;
+ }
+
+ public static class E {
+ public static Class<?> eClass = E.class;
+ public static Class<?> eClassArr = E[].class;
+ public static Class<?> eClassNull;
+ public static Class<?> eClassPrim = Integer.TYPE;
+ }
+
+ public static class E___6 {
+ public static Class<?> eClass;
+ public static Class<?> eClassArr;
+ public static Class<?> eClassNull;
+ public static Class<?> eClassPrim;
+ }
+
+ @Test
+ public void testBase() {
+
+ assert __version__() == 0;
+
+
+ assertEquals(1, A.value());
+ assertEquals(2, B.value());
+
+ __toVersion__(1);
+
+ assertEquals(4, A.value());
+ assertEquals(2, B.value());
+
+ __toVersion__(2);
+
+ assertEquals(6, A.value());
+ assertEquals(3, B.value());
+
+ __toVersion__(3);
+
+ assertEquals(5, A.value());
+ assertEquals(10, B.value());
+
+ __toVersion__(0);
+
+ assertEquals(1, A.value());
+ assertEquals(2, B.value());
+ }
+
+ @Test
+ public void testStaticField() {
+
+ assert __version__() == 0;
+ assertEquals(5, C.value);
+
+ __toVersion__(4);
+ assertEquals(5, C.value);
+
+ __toVersion__(0);
+ assertEquals(5, C.value);
+ }
+
+ @Test
+ public void testStaticFieldUpdated() {
+ assert __version__() == 0;
+ assertEquals(E.class, E.eClass);
+ assertNull(E.eClassNull);
+ assertEquals(E[].class, E.eClassArr);
+
+ __toVersion__(6);
+ assertEquals(E.class, E.eClass);
+ assertNull(E.eClassNull);
+ assertEquals(E[].class, E.eClassArr);
+ }
+
+ @Test
+ public void testManyStaticFields() {
+
+ assert __version__() == 0;
+ assertTrue(D.objectField != null);
+ assertTrue(D.arrayField != null);
+ assertEquals(5, D.integerField);
+ assertEquals(6, D.characterField);
+ assertEquals(7, D.shortField);
+ assertEquals(1.0, D.doubleField, 0.0);
+ assertEquals(2.0f, D.floatField, 0.0);
+ assertEquals(8, D.longField);
+ assertEquals(true, D.booleanField);
+
+ __toVersion__(5);
+ assertTrue(D.objectField != null);
+ assertTrue(D.arrayField != null);
+ assertEquals(5, D.integerField);
+ assertEquals(6, D.characterField);
+ assertEquals(7, D.shortField);
+ assertEquals(1.0, D.doubleField, 0.0);
+ assertEquals(2.0f, D.floatField, 0.0);
+ assertEquals(8, D.longField);
+ assertEquals(true, D.booleanField);
+
+ assertEquals(0, Helper.getAdditionalField());
+ Helper.setAdditionalField(1000);
+ assertEquals(1000, Helper.getAdditionalField());
+
+
+ __toVersion__(0);
+
+ assertTrue(D.objectField != null);
+ assertTrue(D.arrayField != null);
+ assertEquals(5, D.integerField);
+ assertEquals(6, D.characterField);
+ assertEquals(7, D.shortField);
+ assertEquals(1.0, D.doubleField, 0.0);
+ assertEquals(2.0f, D.floatField, 0.0);
+ assertEquals(8, D.longField);
+ assertEquals(true, D.booleanField);
+
+ __toVersion__(5);
+ assertTrue(D.objectField != null);
+ assertTrue(D.arrayField != null);
+ assertEquals(5, D.integerField);
+ assertEquals(6, D.characterField);
+ assertEquals(7, D.shortField);
+ assertEquals(1.0, D.doubleField, 0.0);
+ assertEquals(2.0f, D.floatField, 0.0);
+ assertEquals(8, D.longField);
+ assertEquals(true, D.booleanField);
+
+ assertEquals(0, Helper.getAdditionalField());
+
+ __toVersion__(0);
+ assertTrue(D.objectField != null);
+ assertTrue(D.arrayField != null);
+ assertEquals(5, D.integerField);
+ assertEquals(6, D.characterField);
+ assertEquals(7, D.shortField);
+ assertEquals(1.0, D.doubleField, 0.0);
+ assertEquals(2.0f, D.floatField, 0.0);
+ assertEquals(8, D.longField);
+ assertEquals(true, D.booleanField);
+
+ }
+
+
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/body/StressTest.java b/dcevm/src/test/java/org/dcevm/test/body/StressTest.java
new file mode 100644
index 00000000..3d955810
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/body/StressTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.body;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Thomas Wuerthinger
+ */
+public class StressTest {
+
+ public final static int COUNT = 10;
+
+ // Version 0
+ public static class A {
+
+ public int value() {
+ return 1;
+ }
+ }
+
+ // Version 1
+ public static class A___1 {
+
+ public int value() {
+ return 2;
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testStressSwap() {
+
+ assert __version__() == 0;
+
+ A a = new A();
+
+ for (int i = 0; i < COUNT; i++) {
+
+ assertEquals(1, a.value());
+
+ __toVersion__(1);
+
+ assertEquals(2, a.value());
+
+ __toVersion__(0);
+ }
+
+ assertEquals(1, a.value());
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/eval/AddingInterfaceTest.java b/dcevm/src/test/java/org/dcevm/test/eval/AddingInterfaceTest.java
new file mode 100644
index 00000000..a3bec93d
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/eval/AddingInterfaceTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.eval;
+
+import org.dcevm.test.TestUtil;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+
+/**
+ * Adds an implemented interface to a class and tests whether an instance of this class can then really be treated as an instance of the interface.
+ * Additionally, performs performance measurements of a call to this interface compared to a proxy object.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class AddingInterfaceTest {
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ assert __version__() == 0;
+ }
+
+ public static class A {
+
+ public int getValue() {
+ return 1;
+ }
+ }
+
+ public static interface I {
+
+ public int getValue();
+ }
+
+ public static class A___1 implements I {
+
+ @Override
+ public int getValue() {
+ return 1;
+ }
+ }
+
+ public static class Proxy implements I {
+
+ private A a;
+
+ public Proxy(A a) {
+ this.a = a;
+ }
+
+ @Override
+ public int getValue() {
+ return a.getValue();
+ }
+ }
+
+ @Test
+ public void testAddInterface() {
+
+ A a = new A();
+ Proxy p = new Proxy(a);
+
+ final int N = 100000;
+ final int Z = 1;
+
+
+ __toVersion__(1);
+ I i = (I) a;
+
+ long startTime = System.currentTimeMillis();
+ for (int j = 0; j < Z; j++) {
+ calculateSum(N, i);
+ }
+ long time = System.currentTimeMillis() - startTime;
+ System.out.println(time);
+
+ // Must set to null, otherwise local variable i would violate type safety
+ i = null;
+
+ TestUtil.assertUnsupportedToVersionWithLight(AddingInterfaceTest.class, 0);
+
+ startTime = System.currentTimeMillis();
+ for (int j = 0; j < Z; j++) {
+ calculateSum(N, p);
+ }
+ time = System.currentTimeMillis() - startTime;
+ System.out.println(time);
+ }
+
+ public int calculateSum(int n, I i) {
+ int sum = 0;
+ for (int j = 0; j < n; j++) {
+ sum += i.getValue();
+ }
+ return sum;
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/eval/EvalTestSuite.java b/dcevm/src/test/java/org/dcevm/test/eval/EvalTestSuite.java
new file mode 100644
index 00000000..f9baf6c9
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/eval/EvalTestSuite.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.eval;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * Tests used for evaluation purposes (especially performance measurements).
+ *
+ * @author Thomas Wuerthinger
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ FractionTest.class,
+ GeometryScenario.class,
+ AddingInterfaceTest.class
+})
+public class EvalTestSuite {
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/eval/FractionTest.java b/dcevm/src/test/java/org/dcevm/test/eval/FractionTest.java
new file mode 100644
index 00000000..37ed44f6
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/eval/FractionTest.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.eval;
+
+import org.dcevm.HotSwapTool;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+
+/**
+ * @author Thomas Wuerthinger
+ */
+public class FractionTest {
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ assert __version__() == 0;
+ }
+
+ // Version 0
+ public static class NoChange {
+
+ int i1;
+ int i2;
+ int i3;
+ Object o1;
+ Object o2;
+ Object o3;
+ }
+
+ public static class Change {
+
+ int i1;
+ int i2;
+ int i3;
+ Object o1;
+ Object o2;
+ Object o3;
+ }
+
+ // Version 1
+ public static class Change___1 {
+
+ int i1;
+ int i2;
+ int i3;
+ Object o1;
+ Object o2;
+ Object o3;
+ Object o4;
+ }
+
+ // Version 2
+ public static class Change___2 {
+
+ int i1;
+ int i2;
+ int i3;
+ Object o1;
+ }
+
+ // Version 3
+ public static class Change___3 {
+
+ int i3;
+ int i1;
+ int i2;
+ Object o3;
+ Object o1;
+ Object o2;
+ }
+
+ // Version 3
+ public static class Change___4 {
+
+ int i1;
+ int i2;
+ int i3;
+ Object o1;
+ Object o2;
+ Object o3;
+ }
+
+ // Version 2
+ public static class Change___5 {
+
+ }
+
+ private static List<Long> measurements = new ArrayList<Long>();
+ private final int BASE = 10;
+ private Object[] objects;
+
+ private void clear() {
+ objects = null;
+ System.gc();
+ System.gc();
+ __toVersion__(0);
+ System.gc();
+ System.gc();
+
+ }
+
+ private void init(int count, int percent) {
+ objects = new Object[count];
+ int changed = 0;
+ int unchanged = 0;
+ for (int k = 0; k < count; k++) {
+ if ((count / BASE) * percent <= k/* && k >= 200000*/) {
+ objects[k] = new NoChange();
+ unchanged++;
+ } else {
+ objects[k] = new Change();
+ changed++;
+ }
+ }
+
+ System.gc();
+
+ System.out.println(changed + " changed objects allocated");
+ }
+
+ @Test
+ public void testBase() {
+
+ assert __version__() == 0;
+
+ final int N = 1;
+ final int INC = 4;
+ final int SIZE = 4000;
+
+ int[] benchmarking = new int[]{SIZE};
+ int base = BASE;
+ int start = 0;
+
+ MicroBenchmark[] benchmarks = new MicroBenchmark[]{new GCMicroBenchmark(), new IncreaseMicroBenchmark(), new DecreaseMicroBenchmark(), new ReorderMicroBenchmark(), new NoRealChangeMicroBenchmark(), new BigDecreaseMicroBenchmark()};
+
+ clear();
+ for (int k = 0; k < N; k++) {
+ for (MicroBenchmark m : benchmarks) {
+ for (int i : benchmarking) {
+ System.out.println(m.getClass().getName() + " with " + i + " objects");
+ for (int j = start; j <= base; j += INC) {
+ System.out.println(j);
+ m.init(i);
+ init(i, j);
+ m.doit(i, measurements);
+ clear();
+ }
+ }
+ }
+ }
+
+ System.out.println("Results:");
+ for (long l : measurements) {
+ System.out.println(l);
+ }
+ measurements.clear();
+ }
+}
+
+abstract class MicroBenchmark {
+
+ public void init(int count) {
+ }
+
+ public abstract void doit(int count, List<Long> measurements);
+}
+
+class GCMicroBenchmark extends MicroBenchmark {
+
+ @Override
+ public void doit(int count, List<Long> measurements) {
+ long startTime = System.currentTimeMillis();
+ System.gc();
+ long curTime = System.currentTimeMillis() - startTime;
+ measurements.add(curTime);
+ }
+}
+
+class IncreaseMicroBenchmark extends MicroBenchmark {
+
+ @Override
+ public void doit(int count, List<Long> measurements) {
+ HotSwapTool.resetTimings();
+ __toVersion__(1);
+ measurements.add(HotSwapTool.getTotalTime());
+ }
+}
+
+class DecreaseMicroBenchmark extends MicroBenchmark {
+
+ @Override
+ public void doit(int count, List<Long> measurements) {
+ HotSwapTool.resetTimings();
+ __toVersion__(2);
+ measurements.add(HotSwapTool.getTotalTime());
+ }
+}
+
+class ReorderMicroBenchmark extends MicroBenchmark {
+
+ @Override
+ public void doit(int count, List<Long> measurements) {
+ HotSwapTool.resetTimings();
+ __toVersion__(3);
+ measurements.add(HotSwapTool.getTotalTime());
+ }
+}
+
+class NoRealChangeMicroBenchmark extends MicroBenchmark {
+
+ @Override
+ public void doit(int count, List<Long> measurements) {
+ HotSwapTool.resetTimings();
+ __toVersion__(4);
+ measurements.add(HotSwapTool.getTotalTime());
+ }
+}
+
+class BigDecreaseMicroBenchmark extends MicroBenchmark {
+
+ @Override
+ public void doit(int count, List<Long> measurements) {
+ HotSwapTool.resetTimings();
+ __toVersion__(5);
+ measurements.add(HotSwapTool.getTotalTime());
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/eval/GeometryScenario.java b/dcevm/src/test/java/org/dcevm/test/eval/GeometryScenario.java
new file mode 100644
index 00000000..f671b6ca
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/eval/GeometryScenario.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package org.dcevm.test.eval;
+
+import org.dcevm.test.TestUtil;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * A small geometry example application including a Point and a Rectangle class.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class GeometryScenario {
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ // Version 0
+ public static class Point {
+
+ private int x;
+ private int y;
+
+ public Point(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public boolean isBottomRightOf(Point p) {
+ return p.x >= x && p.y >= y;
+ }
+
+ public boolean isTopLeftOf(Point p) {
+ return p.x <= x && p.y <= y;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public int getY() {
+ return y;
+ }
+ }
+
+ public static interface IFigure {
+
+ public boolean isHitAt(Point p);
+ }
+
+ public static class Rectangle {
+
+ private Point topLeft;
+ private Point bottomRight;
+
+ public Rectangle(Point p1, Point p2) {
+ topLeft = p1;
+ bottomRight = p2;
+ }
+
+ public boolean isHitAt(Point p) {
+ return p.isBottomRightOf(topLeft) && !p.isTopLeftOf(bottomRight);
+ }
+
+ public Point getTopLeft() {
+ return topLeft;
+ }
+
+ public Point getBottomRight() {
+ return bottomRight;
+ }
+
+ public static Rectangle create(Point p) {
+ return (Rectangle) (Object) (new Rectangle___1(p));
+ }
+ }
+
+ // Version 1
+ public static class Rectangle___1 implements IFigure {
+
+ private Point topLeft;
+ private Point center;
+ private Point bottomRight;
+
+ public Point getCenter() {
+ return center;
+ }
+
+ public Rectangle___1(Point p) {
+ topLeft = p;
+ bottomRight = p;
+ }
+
+ @Override
+ public boolean isHitAt(Point p) {
+ return p.isBottomRightOf(topLeft) && !p.isTopLeftOf(bottomRight);
+ }
+
+ public Point getTopLeft() {
+ return topLeft;
+ }
+
+ public Point getBottomRight() {
+ return bottomRight;
+ }
+
+ public static Rectangle create(Point p) {
+ return (Rectangle) (Object) (new Rectangle___1(p));
+ }
+ }
+
+ public static class Point___1 {
+
+ private char x1;
+ private int y;
+ private char x2;
+
+ public boolean isBottomRightOf(Point p) {
+ return p.x >= x1 && p.y >= y;
+ }
+
+ public boolean isTopLeftOf(Point p) {
+ return p.x <= x1 && p.y <= y;
+ }
+
+ public int getY() {
+ return y;
+ }
+
+ public int getX() {
+ return x1;
+ }
+
+ public char getX2() {
+ return x2;
+ }
+ }
+
+ @Test
+ public void testContructorChange() {
+
+ assert __version__() == 0;
+
+ final Point p1 = new Point(1, 2);
+ final Point p2 = new Point(3, 4);
+ final Rectangle r1 = new Rectangle(p1, p2);
+
+ assertEquals(1, p1.getX());
+ assertEquals(2, p1.getY());
+ assertEquals(3, p2.getX());
+ assertEquals(4, p2.getY());
+ assertEquals(p1, r1.getTopLeft());
+ assertEquals(p2, r1.getBottomRight());
+
+ __toVersion__(1);
+
+ final Rectangle r4 = Rectangle.create(p1);
+ assertEquals(0, p1.getX());
+ assertEquals(2, p1.getY());
+ assertEquals(0, p2.getX());
+ assertEquals(4, p2.getY());
+ assertEquals(p1, r4.getTopLeft());
+ assertEquals(p1, r4.getBottomRight());
+
+ TestUtil.assertUnsupportedWithLight(new Runnable() {
+
+ @Override
+ public void run() {
+ __toVersion__(0);
+ assertEquals(0, p1.getX());
+ assertEquals(2, p1.getY());
+ assertEquals(0, p2.getX());
+ assertEquals(4, p2.getY());
+ assertEquals(p1, r4.getTopLeft());
+ assertEquals(p1, r4.getBottomRight());
+ }
+ });
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/fields/ComplexFieldTest.java b/dcevm/src/test/java/org/dcevm/test/fields/ComplexFieldTest.java
new file mode 100644
index 00000000..e7562349
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/fields/ComplexFieldTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.fields;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Complex field test.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ComplexFieldTest {
+
+ // Version 0
+ public static class A {
+ public byte byteFld = 10;
+ public short shortFld = 20;
+ public int intFld = 30;
+ public long longFld = 40L;
+ public float floatFld = 50.2F;
+ public double doubleFld = 60.3D;
+ public char charFld = 'b';
+ public boolean booleanFld = true;
+ public String stringFld = "OLD";
+ }
+
+ // Version 1
+ public static class A___1 {
+ public byte byteFld = 11;
+ public short shortFld = 22;
+ public int intFld = 33;
+ public long longFld = 44L;
+ public float floatFld = 55.5F;
+ public double doubleFld = 66.6D;
+ public char charFld = 'c';
+ public boolean booleanFld = false;
+ public String stringFld = "NEW";
+
+ // completely new instance fields are below
+ public int intComplNewFld = 333;
+ public long longComplNewFld = 444L;
+ public String stringComplNewFld = "completely new String field";
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ /**
+ * Checks that the given object is unmodified (i.e. the values of the fields are correct)
+ *
+ * @param a the object to be checked
+ */
+ private void assertObjectOK(A a) {
+ assertEquals(10, a.byteFld);
+ assertEquals(20, a.shortFld);
+ assertEquals(30, a.intFld);
+ assertEquals(40L, a.longFld);
+ assertEquals(50.2F, a.floatFld, 0.01);
+ assertEquals(60.3D, a.doubleFld, 0.01);
+ assertEquals('b', a.charFld);
+ assertEquals(true, a.booleanFld);
+ assertEquals("OLD", a.stringFld);
+ }
+
+ @Test
+ public void testComplexFieldChange() {
+ assert __version__() == 0;
+ A a = new A();
+ assertObjectOK(a);
+ __toVersion__(1);
+ assertObjectOK(a);
+ __toVersion__(0);
+ assertObjectOK(a);
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/fields/EnumTest.java b/dcevm/src/test/java/org/dcevm/test/fields/EnumTest.java
new file mode 100644
index 00000000..a5443bef
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/fields/EnumTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.fields;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * @author Ivan Dubrov
+ */
+public class EnumTest {
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ static enum A {
+ FIRST,
+ SECOND;
+ }
+
+ static enum A___1 {
+ SECOND,
+ THIRD,
+ FOURTH;
+ }
+
+ @Test
+ @Ignore
+ public void testEnumFields() throws Exception {
+ assertEquals(2, A.values().length);
+ assertNotNull(A.values()[0]);
+ assertNotNull(A.values()[1]);
+
+ __toVersion__(1);
+
+ assertEquals(3, A.values().length);
+ assertNotNull(A.values()[0]);
+ assertNotNull(A.values()[1]);
+ assertNotNull(A.values()[2]);
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/fields/FieldAlignmentTest.java b/dcevm/src/test/java/org/dcevm/test/fields/FieldAlignmentTest.java
new file mode 100644
index 00000000..ebd47771
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/fields/FieldAlignmentTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.fields;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+
+/**
+ * Complex field test.
+ *
+ * @author Ivan Dubrov
+ */
+public class FieldAlignmentTest {
+
+ // Version 0
+ public static class A {
+ }
+
+ // Version 1
+ public static class A___1 {
+ public boolean booleanFld; // note: gap betweer booleanFld and stringFld, should be properly filled.
+ public String stringFld = "NEW";
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testComplexFieldChange() {
+ assert __version__() == 0;
+ A a = new A();
+ __toVersion__(1);
+ System.gc(); // induce GC to verify that gap is properly filled
+ __toVersion__(0);
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/fields/FieldChangedOrderTest.java b/dcevm/src/test/java/org/dcevm/test/fields/FieldChangedOrderTest.java
new file mode 100644
index 00000000..99f03afa
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/fields/FieldChangedOrderTest.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.fields;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test that changes the order of two int fields.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class FieldChangedOrderTest {
+
+ // Version 0
+ public static class A {
+
+ public int value1;
+ public int value2;
+
+ public A() {
+ value1 = 1;
+ value2 = 2;
+ }
+
+ public int getValue1() {
+ return value1;
+ }
+
+ public int getValue2() {
+ return value2;
+ }
+ }
+
+ public static class B {
+
+ public static int getStaticValue1(A a) {
+ return a.value1;
+ }
+
+ public static int getStaticValue2(A a) {
+ return a.value2;
+ }
+ }
+
+ // Version 1
+ public static class A___1 {
+
+ public int value2;
+ public int value1;
+
+ public int getValue1() {
+ return value1;
+ }
+
+ public int getValue2() {
+ return value2;
+ }
+ }
+
+ public static class B___1 {
+
+ public static int getStaticValue1(A a) {
+ return a.value1;
+ }
+
+ public static int getStaticValue2(A a) {
+ return a.value2;
+ }
+ }
+
+ // Version 2
+ public static class A___2 {
+
+ public int tmp1;
+ public int value2;
+ public int tmp2;
+ public int value1;
+ public int tmp3;
+
+ public int getValue1() {
+ return value1;
+ }
+
+ public int getValue2() {
+ return value2;
+ }
+ }
+
+ // Version 3
+ public static class A___3 {
+
+ public int tmp1;
+ public int value2;
+
+ public int getValue1() {
+ return tmp1;
+ }
+
+ public int getValue2() {
+ return value2;
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testRenameField() {
+ assert __version__() == 0;
+ A a = new A();
+ assertObjectOK(a);
+ __toVersion__(3);
+ assertEquals(0, a.getValue1());
+ assertEquals(2, a.getValue2());
+ __toVersion__(0);
+ assertEquals(0, a.getValue1());
+ assertEquals(2, a.getValue2());
+ }
+
+ @Test
+ public void testSimpleOrderChange() {
+ assert __version__() == 0;
+ A a = new A();
+ assertObjectOK(a);
+ __toVersion__(1);
+ assertObjectOK(a);
+ __toVersion__(0);
+ assertObjectOK(a);
+ }
+
+ /**
+ * Checks that the given object is unmodified (i.e. the values of the fields are correct)
+ *
+ * @param a the object to be checked
+ */
+ private void assertObjectOK(A a) {
+ assertEquals(1, a.getValue1());
+ assertEquals(2, a.getValue2());
+ assertEquals(1, B.getStaticValue1(a));
+ assertEquals(2, B.getStaticValue2(a));
+ assertEquals(1, a.value1);
+ assertEquals(2, a.value2);
+ }
+
+ @Test
+ public void testSimpleOrderChangeWithNewTempFields() {
+ assert __version__() == 0;
+ A a = new A();
+ assertObjectOK(a);
+ __toVersion__(2);
+ assertObjectOK(a);
+ __toVersion__(0);
+ assertObjectOK(a);
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/fields/FieldModificationTest.java b/dcevm/src/test/java/org/dcevm/test/fields/FieldModificationTest.java
new file mode 100644
index 00000000..3529e6ad
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/fields/FieldModificationTest.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.fields;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Thomas Wuerthinger
+ */
+public class FieldModificationTest {
+
+ // Version 0
+ public static class A {
+
+ public int val0;
+ public int val1;
+ public int val2;
+ public int val3;
+ public int val4;
+ public int val5;
+ public int val6;
+ public int val7;
+
+ public void increaseAllByOne() {
+ val0++;
+ val1++;
+ val2++;
+ val3++;
+ val4++;
+ val5++;
+ val6++;
+ val7++;
+ }
+
+ public int sum() {
+ return val0 + val1 + val2 + val3 + val4 + val5 + val6 + val7;
+ }
+ }
+
+ // Version 1
+ public static class A___1 {
+
+ public int val0;
+
+ public void increaseAllByOne() {
+ val0++;
+ }
+
+ public int sum() {
+ return val0;
+ }
+ }
+
+ // Version 2
+ public static class A___2 {
+
+ public int val0;
+ public int val1;
+ public int val2;
+ public int val3;
+ public int val4;
+ public int val5;
+ public int val6;
+ public int val7;
+ public int val8;
+ public int val9;
+ public int val10;
+ public int val11;
+ public int val12;
+ public int val13;
+ public int val14;
+ public int val15;
+
+ public int sum() {
+ return val0 + val1 + val2 + val3 + val4 + val5 + val6 + val7 + val8 + val9 + val10 + val11 + val12 + val13 + val14 + val15;
+ }
+
+ public void increaseAllByOne() {
+ val0++;
+ val1++;
+ val2++;
+ val3++;
+ val4++;
+ val5++;
+ val6++;
+ val7++;
+ val8++;
+ val9++;
+ val10++;
+ val11++;
+ val12++;
+ val13++;
+ val14++;
+ val15++;
+ }
+ }
+
+ // Version 3
+ public static class A___3 {
+
+ public int val6;
+ public int val0;
+ public int val7;
+ public int val1;
+ public int val2;
+ public int val5;
+ public int val3;
+ public int val4;
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testReorder() {
+
+ A a = new A();
+
+ a.val0 = 0;
+ a.val1 = 1;
+ a.val2 = 2;
+ a.val3 = 3;
+ a.val4 = 4;
+ a.val5 = 5;
+ a.val6 = 6;
+ a.val7 = 7;
+ }
+
+ @Test
+ public void testIncreaseFirst() {
+
+ A a = new A();
+
+ a.val0 = 0;
+ a.val1 = 1;
+ a.val2 = 2;
+ a.val3 = 3;
+ a.val4 = 4;
+ a.val5 = 5;
+ a.val6 = 6;
+ a.val7 = 7;
+
+ assertEquals(0, a.val0);
+ assertEquals(1, a.val1);
+ assertEquals(2, a.val2);
+ assertEquals(3, a.val3);
+ assertEquals(4, a.val4);
+ assertEquals(5, a.val5);
+ assertEquals(6, a.val6);
+ assertEquals(7, a.val7);
+ assertEquals(0 + 1 + 2 + 3 + 4 + 5 + 6 + 7, a.sum());
+
+ __toVersion__(2);
+
+ assertEquals(0, a.val0);
+ assertEquals(1, a.val1);
+ assertEquals(2, a.val2);
+ assertEquals(3, a.val3);
+ assertEquals(4, a.val4);
+ assertEquals(5, a.val5);
+ assertEquals(6, a.val6);
+ assertEquals(7, a.val7);
+ assertEquals(0 + 1 + 2 + 3 + 4 + 5 + 6 + 7, a.sum());
+
+ a.increaseAllByOne();
+ assertEquals(0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 16, a.sum());
+
+ __toVersion__(0);
+
+ assertEquals(0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8, a.sum());
+ assertEquals(1, a.val0);
+ assertEquals(2, a.val1);
+ assertEquals(3, a.val2);
+ assertEquals(4, a.val3);
+ assertEquals(5, a.val4);
+ assertEquals(6, a.val5);
+ assertEquals(7, a.val6);
+ assertEquals(8, a.val7);
+
+ __toVersion__(2);
+
+ assertEquals(0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8, a.sum());
+ assertEquals(1, a.val0);
+ assertEquals(2, a.val1);
+ assertEquals(3, a.val2);
+ assertEquals(4, a.val3);
+ assertEquals(5, a.val4);
+ assertEquals(6, a.val5);
+ assertEquals(7, a.val6);
+ assertEquals(8, a.val7);
+
+ a.increaseAllByOne();
+
+ assertEquals(0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 16, a.sum());
+ assertEquals(2, a.val0);
+ assertEquals(3, a.val1);
+ assertEquals(4, a.val2);
+ assertEquals(5, a.val3);
+ assertEquals(6, a.val4);
+ assertEquals(7, a.val5);
+ assertEquals(8, a.val6);
+ assertEquals(9, a.val7);
+ __toVersion__(0);
+
+ assertEquals(0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 16, a.sum());
+ assertEquals(2, a.val0);
+ assertEquals(3, a.val1);
+ assertEquals(4, a.val2);
+ assertEquals(5, a.val3);
+ assertEquals(6, a.val4);
+ assertEquals(7, a.val5);
+ assertEquals(8, a.val6);
+ assertEquals(9, a.val7);
+ }
+
+ @Test
+ public void testAddRemoveField() {
+
+ assert __version__() == 0;
+
+ A a = new A();
+
+ assertEquals(0, a.val0);
+ assertEquals(0, a.val1);
+
+ __toVersion__(1);
+
+ a.val0 = 1234;
+
+ __toVersion__(0);
+
+ assertEquals(1234, a.val0);
+ assertEquals(0, a.val1);
+
+ a.val1 = 1234;
+
+ assertEquals(1234, a.val0);
+ assertEquals(1234, a.val1);
+
+ __toVersion__(1);
+
+ assertEquals(1234, a.val0);
+
+ __toVersion__(0);
+
+ assertEquals(1234, a.val0);
+ assertEquals(0, a.val1);
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/fields/FieldsTestSuite.java b/dcevm/src/test/java/org/dcevm/test/fields/FieldsTestSuite.java
new file mode 100644
index 00000000..55ce5941
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/fields/FieldsTestSuite.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.fields;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * Class redefinition tests that may change the methods and fields of class, but do not change the superklass or the implemented
+ * interface.
+ *
+ * @author Thomas Wuerthinger
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ FieldChangedOrderTest.class,
+ FieldModificationTest.class,
+ ObjectStressTest.class,
+ YieldTest.class,
+ ComplexFieldTest.class,
+ FieldAlignmentTest.class,
+ StringFieldTest.class,
+ RedefinePrivateFieldTest.class,
+ EnumTest.class
+})
+public class FieldsTestSuite {
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/fields/ObjectStressTest.java b/dcevm/src/test/java/org/dcevm/test/fields/ObjectStressTest.java
new file mode 100644
index 00000000..5109fb9b
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/fields/ObjectStressTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.fields;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Thomas Wuerthinger
+ */
+public class ObjectStressTest {
+
+ private final int COUNT = 10000;
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ // Version 0
+ public static class A {
+
+ public A thisPointer;
+ public int i1;
+ public int i2;
+ public int i3;
+ public int i4;
+ public int i5;
+ public int i6;
+ public int i7;
+ public int i8;
+ public int i9;
+ public int i10;
+
+ public int sum() {
+ return i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10;
+ }
+ }
+
+ // Version 1
+ public static class A___1 {
+
+ public int i1;
+ public int i2;
+ public int i8;
+ public int i3;
+ public int i4;
+ public int i10;
+ public int i5;
+ public int i6;
+ public int i7;
+ public int i9;
+ public A thisPointer;
+
+ public int sum() {
+ return i1 * i2 * i3 * i4 * i5 * i6 * i7 * i8 * i9 * i10;
+ }
+ }
+
+ @Test
+ public void testLotsOfObjects() {
+
+ assert __version__() == 0;
+
+ A[] arr = new A[COUNT];
+ for (int i = 0; i < arr.length; i++) {
+ arr[i] = new A();
+ arr[i].thisPointer = arr[i];
+ arr[i].i1 = 1;
+ arr[i].i2 = 2;
+ arr[i].i3 = 3;
+ arr[i].i4 = 4;
+ arr[i].i5 = 5;
+ arr[i].i6 = 6;
+ arr[i].i7 = 7;
+ arr[i].i8 = 8;
+ arr[i].i9 = 9;
+ arr[i].i10 = 10;
+ }
+
+
+ __toVersion__(1);
+
+ for (int i = 0; i < arr.length; i++) {
+ assertEquals(1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10, arr[i].sum());
+ assertEquals(arr[i].thisPointer, arr[i]);
+ }
+
+ __toVersion__(0);
+
+ for (int i = 0; i < arr.length; i++) {
+ assertEquals(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10, arr[i].sum());
+ assertEquals(arr[i].thisPointer, arr[i]);
+ }
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/fields/RedefinePrivateFieldTest.java b/dcevm/src/test/java/org/dcevm/test/fields/RedefinePrivateFieldTest.java
new file mode 100644
index 00000000..c2ea1dea
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/fields/RedefinePrivateFieldTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.fields;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests redefinition of a class such that old code still accesses a redefined private field.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class RedefinePrivateFieldTest {
+
+ // Version 0
+ public static class A {
+
+ private int f1;
+
+ public A() {
+ f1 = 5;
+ }
+
+ public int foo() {
+ int result = f1;
+ __toVersion__(1);
+ result += f1;
+ return result;
+ }
+ }
+
+ // Version 1
+ public static class A___1 {
+
+ int f0;
+ int f1;
+
+ public int foo() {
+ return -1;
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testRedefinePrivateField() {
+
+ assert __version__() == 0;
+
+ A a = new A();
+
+ assertEquals(10, a.foo());
+
+ assert __version__() == 1;
+
+ assertEquals(-1, a.foo());
+
+ __toVersion__(0);
+
+ assertEquals(10, a.foo());
+
+ assert __version__() == 1;
+
+ assertEquals(-1, a.foo());
+
+ __toVersion__(0);
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/fields/StringFieldTest.java b/dcevm/src/test/java/org/dcevm/test/fields/StringFieldTest.java
new file mode 100644
index 00000000..2bf7167a
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/fields/StringFieldTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.fields;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Complex field test.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class StringFieldTest {
+
+ // Version 0
+ public static class A {
+ public String stringFld = "OLD";
+ }
+
+ // Version 1
+ public static class A___1 {
+ public String stringFld = "NEW";
+ public int intComplNewFld = 333;
+ public long longComplNewFld = 444L;
+ public String stringComplNewFld = "completely new String field";
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ /**
+ * Checks that the given object is unmodified (i.e. the values of the fields are correct)
+ *
+ * @param a the object to be checked
+ */
+ private void assertObjectOK(A a) {
+ assertEquals("OLD", a.stringFld);
+ }
+
+ @Test
+ public void testComplexFieldChange() {
+ assert __version__() == 0;
+ A a = new A();
+ assertObjectOK(a);
+ __toVersion__(1);
+ assertObjectOK(a);
+ __toVersion__(0);
+ assertObjectOK(a);
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/fields/YieldTest.java b/dcevm/src/test/java/org/dcevm/test/fields/YieldTest.java
new file mode 100644
index 00000000..0f5dc40c
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/fields/YieldTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.fields;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test case that produces a list of integer values recursively.
+ * The recursive function does not contain a conditional statement.
+ * The recursion is stopped by swapping the recursive method with a different non-recursive implementation.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class YieldTest {
+
+ // Version 0
+ public static class Base {
+
+ protected List<Integer> arr = new ArrayList<Integer>();
+
+ public void reset() {
+ __toVersion__(0);
+ }
+
+ public void next() {
+ __toVersion__(__version__() + 1);
+ }
+ }
+
+ public static abstract class A extends Base {
+
+ public List<Integer> gen() {
+ arr.add(produce());
+ next();
+ return gen();
+ }
+
+ public abstract int produce();
+ }
+
+ public static class B extends A {
+
+ @Override
+ public int produce() {
+ return 1;
+ }
+ }
+
+ public static class B___10 extends A {
+
+ @Override
+ public int produce() {
+ return 2;
+ }
+ }
+
+ public static class B___20 extends A {
+
+ private int x;
+
+ @Override
+ public int produce() {
+ return ++x;
+ }
+ }
+
+ public static class A___30 extends Base {
+
+ public List<Integer> gen() {
+ reset();
+ return arr;
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testYield() {
+
+ assert __version__() == 0;
+
+ B b = new B();
+ assertEquals(Arrays.asList(
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10), b.gen());
+ assert __version__() == 0;
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/methods/AddMethodTest.java b/dcevm/src/test/java/org/dcevm/test/methods/AddMethodTest.java
new file mode 100644
index 00000000..7a56b577
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/methods/AddMethodTest.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package org.dcevm.test.methods;
+
+import org.dcevm.test.TestUtil;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests for adding / removing methods in a single class.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class AddMethodTest {
+
+ // Version 0
+ public static class A {
+ public int value(int newVersion) {
+ return newVersion;
+ }
+ }
+
+ // Version 1
+ public static class A___1 {
+
+ public int value(int newVersion) {
+
+ int x = 1;
+ try {
+ x = 2;
+ } catch (NumberFormatException e) {
+ x = 3;
+ } catch (Exception e) {
+ x = 4;
+ } finally {
+ x = x * 2;
+ }
+ __toVersion__(newVersion);
+ throw new IllegalArgumentException();
+ }
+ }
+
+ // Version 2
+ public static class A___2 {
+
+ public int value2() {
+ return 2;
+ }
+
+ public int value(int newVersion) {
+
+ int x = 1;
+ try {
+ x = 2;
+ } catch (NumberFormatException e) {
+ x = 3;
+ } catch (Exception e) {
+ x = 4;
+ } finally {
+ x = x * 2;
+ }
+ __toVersion__(newVersion);
+ throw new IllegalArgumentException();
+ }
+
+ public int value3() {
+ return 3;
+ }
+
+ public int value4() {
+ return 4;
+ }
+
+ public int value5() {
+ return 5;
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ private void checkLineNumbers(int first, int second) {
+ assertTrue("Must have different line numbers (A.value is an EMCP method and therefore execution has to be transferred). Exception line numbers: " + first + " and " + second, first != second);
+ }
+
+ @Test
+ public void testAddMethodToKlassWithEMCPExceptionMethod() {
+
+ assert __version__() == 0;
+
+ final A a = new A();
+
+ assertEquals(1, a.value(1));
+
+ __toVersion__(1);
+
+ int firstLineNumber = TestUtil.assertException(IllegalArgumentException.class, new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(4, a.value(1));
+ }
+ });
+
+ int secondLineNumber = TestUtil.assertException(IllegalArgumentException.class, new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(4, a.value(2));
+ }
+ });
+
+ checkLineNumbers(firstLineNumber, secondLineNumber);
+
+ assert __version__() == 2;
+
+ int newFirstLineNumber = TestUtil.assertException(IllegalArgumentException.class, new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(4, a.value(2));
+ }
+ });
+
+ assertEquals(secondLineNumber, newFirstLineNumber);
+
+ int newSecondLineNumber = TestUtil.assertException(IllegalArgumentException.class, new Runnable() {
+ @Override
+ public void run() {
+ assertEquals(4, a.value(1));
+ }
+ });
+
+ assertEquals(newSecondLineNumber, firstLineNumber);
+ checkLineNumbers(firstLineNumber, secondLineNumber);
+
+ __toVersion__(0);
+ assertEquals(1, a.value(1));
+ assert __version__() == 0;
+ }
+} \ No newline at end of file
diff --git a/dcevm/src/test/java/org/dcevm/test/methods/AnnotationTest.java b/dcevm/src/test/java/org/dcevm/test/methods/AnnotationTest.java
new file mode 100644
index 00000000..bb25162f
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/methods/AnnotationTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package org.dcevm.test.methods;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.lang.annotation.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for adding / removing annotations on methods, fields and classes.
+ *
+ * @author Thomas Wuerthinger
+ * @author Jiri Bubnik
+ */
+public class AnnotationTest {
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
+ public @interface TestAnnotation {
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
+ public @interface TestAnnotation2 {
+ }
+
+
+ // Version 0
+ public static class A {
+ public int testField;
+
+ public void testMethod() {
+ }
+ }
+
+ // Version 1
+ @TestAnnotation
+ public static class A___1 {
+ @TestAnnotation
+ public int testField;
+
+ @TestAnnotation
+ public void testMethod() {
+ }
+ }
+
+ // Version 2
+ @TestAnnotation2
+ public static class A___2 {
+ @TestAnnotation2
+ public int testField;
+
+ @TestAnnotation2
+ public void testMethod() {
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ private void checkAnnotation(Class<?> c, Class<? extends Annotation> expectedAnnotation) throws NoSuchMethodException, NoSuchFieldException {
+ Class<? extends Annotation> annotation = c.getAnnotation(expectedAnnotation).annotationType();
+ assertEquals(expectedAnnotation, annotation);
+ Method m = c.getMethod("testMethod");
+ annotation = m.getAnnotation(expectedAnnotation).annotationType();
+ assertEquals(expectedAnnotation, annotation);
+ Field f = c.getField("testField");
+ annotation = f.getAnnotation(expectedAnnotation).annotationType();
+ assertEquals(expectedAnnotation, annotation);
+ }
+
+ private void checkAnnotationMissing(Class<A> c) throws NoSuchMethodException, NoSuchFieldException {
+ assertEquals(0, c.getAnnotations().length);
+ assertEquals(0, c.getField("testField").getAnnotations().length);
+ assertEquals(0, c.getMethod("testMethod").getAnnotations().length);
+ }
+
+ @Test
+ public void testAddMethodToKlassWithEMCPExceptionMethod() throws NoSuchMethodException, NoSuchFieldException {
+
+ assert __version__() == 0;
+ checkAnnotationMissing(A.class);
+ __toVersion__(1);
+ checkAnnotation(A.class, TestAnnotation.class);
+ __toVersion__(2);
+ checkAnnotation(A.class, TestAnnotation2.class);
+ __toVersion__(0);
+ checkAnnotationMissing(A.class);
+ }
+
+} \ No newline at end of file
diff --git a/dcevm/src/test/java/org/dcevm/test/methods/ClassObjectHashcodeTest.java b/dcevm/src/test/java/org/dcevm/test/methods/ClassObjectHashcodeTest.java
new file mode 100644
index 00000000..846c86e4
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/methods/ClassObjectHashcodeTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package org.dcevm.test.methods;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Redefines a class and tests that the identity hashcode of the
+ * java.lang.Class object is retained. Also tests the combination of
+ * locking and retrieving the hashcode.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ClassObjectHashcodeTest {
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ // Version 0
+ public static class A {
+
+ public int value() {
+ return 1;
+ }
+ }
+
+ // Version 1
+ public static class A___1 {
+
+ public int value() {
+ return 2;
+ }
+ }
+
+ @Test
+ public void testClassObjectHashcode() {
+ A a = new A();
+ Class clazz = a.getClass();
+ int hashCode = clazz.hashCode();
+ assertEquals(1, a.value());
+ __toVersion__(1);
+ assertEquals(2, a.value());
+ assertEquals(hashCode, clazz.hashCode());
+ assertEquals(hashCode, a.getClass().hashCode());
+ __toVersion__(0);
+ synchronized (clazz) {
+ assertEquals(1, a.value());
+ assertEquals(hashCode, clazz.hashCode());
+ assertEquals(hashCode, a.getClass().hashCode());
+ __toVersion__(1);
+ assertEquals(2, a.value());
+ assertTrue(a.getClass() == clazz);
+ assertTrue(a.getClass() == ClassObjectHashcodeTest.A.class);
+ assertEquals(hashCode, clazz.hashCode());
+ assertEquals(hashCode, a.getClass().hashCode());
+ }
+ assertEquals(2, a.value());
+ assertTrue(a.getClass() == clazz);
+ __toVersion__(0);
+ assertTrue(a.getClass() == clazz);
+ assertEquals(hashCode, clazz.hashCode());
+ assertEquals(hashCode, a.getClass().hashCode());
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/methods/ClassObjectSynchronizationTest.java b/dcevm/src/test/java/org/dcevm/test/methods/ClassObjectSynchronizationTest.java
new file mode 100644
index 00000000..8bf5eab5
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/methods/ClassObjectSynchronizationTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package org.dcevm.test.methods;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Redefines a class and tests that the lock on the java.lang.Class object
+ * is retained. Also tests that the object identity of the java.lang.Class
+ * object is not changed.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ClassObjectSynchronizationTest {
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ // Version 0
+ public static class A {
+
+ public int value() {
+ return 1;
+ }
+ }
+
+ // Version 1
+ public static class A___1 {
+
+ public int value() {
+ return 2;
+ }
+ }
+
+ @Test
+ public void testClassObjectSynchronization() {
+ A a = new A();
+ Class clazz = a.getClass();
+ synchronized (clazz) {
+ assertEquals(1, a.value());
+ __toVersion__(1);
+ assertEquals(2, a.value());
+ assertTrue(a.getClass() == clazz);
+ assertTrue(a.getClass() == ClassObjectSynchronizationTest.A.class);
+ }
+ assertEquals(2, a.value());
+ assertTrue(a.getClass() == clazz);
+ __toVersion__(0);
+ assertTrue(a.getClass() == clazz);
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/methods/ClassReflectionTest.java b/dcevm/src/test/java/org/dcevm/test/methods/ClassReflectionTest.java
new file mode 100644
index 00000000..75fc38b4
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/methods/ClassReflectionTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.methods;
+
+import junit.framework.Assert;
+import org.dcevm.test.TestUtil;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.lang.ref.SoftReference;
+import java.lang.reflect.Method;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Testing correct reflection functionality after class redefinition.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ClassReflectionTest {
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ // Version 0
+ public static class A {
+
+ public int value() {
+ return 1;
+ }
+ }
+
+ public static class B extends A {
+
+ @Override
+ public int value() {
+ return 2;
+ }
+ }
+
+ public static class C extends A {
+
+ @Override
+ public int value() {
+ return 3;
+ }
+ }
+
+ // Version 1
+ public static class A___1 {
+
+ public int value() {
+ return 1;
+ }
+
+ public int value2() {
+ return 2;
+ }
+ }
+
+ // Version 2
+ public static class C___2 extends B {
+
+ @Override
+ public int value() {
+ return super.value();
+ }
+ }
+
+ private void assertIsSuper(Class<?> s, Class<?> c) {
+ assertEquals(s, c.getSuperclass());
+ }
+
+ private void assertIsNotSuper(Class<?> s, Class<?> c) {
+ Assert.assertFalse(s.equals(c.getSuperclass()));
+ }
+
+ @Test
+ public void testClassReflection() {
+
+ checkWeakReference();
+ assert __version__() == 0;
+
+ final A a = new A();
+ final B b = new B();
+ final C c = new C();
+
+ assertIsSuper(A.class, B.class);
+ assertIsSuper(A.class, C.class);
+ assertIsNotSuper(B.class, C.class);
+
+ assertEquals(1, a.value());
+ assertEquals(2, b.value());
+ assertEquals(3, c.value());
+
+ __toVersion__(2);
+
+ assertIsSuper(A.class, B.class);
+ assertIsSuper(B.class, C.class);
+ assertIsNotSuper(A.class, C.class);
+
+ assertEquals(1, a.value());
+ assertEquals(2, b.value());
+ assertEquals(2, c.value());
+
+ TestUtil.assertUnsupportedWithLight(new Runnable() {
+ @Override
+ public void run() {
+ __toVersion__(0);
+
+ assertIsSuper(A.class, B.class);
+ assertIsSuper(A.class, C.class);
+ assertIsNotSuper(B.class, C.class);
+
+ assertEquals(1, a.value());
+ assertEquals(2, b.value());
+ assertEquals(3, c.value());
+ }
+ });
+ }
+
+ public void checkWeakReference() {
+ A a = new A();
+ Class<?> strongRef = a.getClass();
+ SoftReference<Class<?>> softRef = new SoftReference<Class<?>>(a.getClass());
+
+ assertEquals(1, a.value());
+ __toVersion__(1);
+ assertEquals(1, a.value());
+ Assert.assertTrue(strongRef == softRef.get());
+
+ __toVersion__(0);
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/methods/DeleteActiveMethodTest.java b/dcevm/src/test/java/org/dcevm/test/methods/DeleteActiveMethodTest.java
new file mode 100644
index 00000000..da957093
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/methods/DeleteActiveMethodTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.methods;
+
+import junit.framework.Assert;
+import org.dcevm.test.TestUtil;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test cases that delete a method that is currently active on the stack.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class DeleteActiveMethodTest {
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ // Version 0
+ public static class A {
+
+ boolean firstCall;
+
+ public int value() {
+ firstCall = true;
+ return helperValue();
+ }
+
+ public int helperValue() {
+
+ if (!firstCall) {
+ return -1;
+ }
+ firstCall = false;
+
+ Thread t = new Thread(new Runnable() {
+
+ @Override
+ public void run() {
+ __toVersion__(1);
+ }
+ });
+ t.start();
+
+ try {
+ do {
+ this.helperValue();
+ } while (t.isAlive());
+ this.helperValue();
+ Assert.fail("Exception expected!");
+ } catch (NoSuchMethodError e) {
+ }
+
+ try {
+ t.join();
+ } catch (InterruptedException e) {
+ }
+
+ return 1;
+ }
+ }
+
+ public static class B {
+
+ public int fac(int x) {
+ if (x == 0) {
+ __toVersion__(1);
+ }
+
+ return x * fac(x - 1);
+ }
+ }
+
+ // Version 1
+ public static class A___1 {
+
+ boolean firstCall;
+
+ public int value() {
+ __toVersion__(0);
+ return 2;
+ }
+ }
+
+ public static class B___1 {
+ }
+
+ @Test
+ public void testDeleteActiveMethodSimple() {
+ assert __version__() == 0;
+
+ final B b = new B();
+ TestUtil.assertException(NoSuchMethodError.class, new Runnable() {
+ @Override
+ public void run() {
+ b.fac(5);
+ }
+ });
+
+ assert __version__() == 1;
+
+ __toVersion__(0);
+ assert __version__() == 0;
+ }
+
+ @Test
+ public void testDeleteActiveMethod() {
+ assert __version__() == 0;
+
+ A a = new A();
+
+ assertEquals(1, a.value());
+ assert __version__() == 1;
+
+ assertEquals(2, a.value());
+ assert __version__() == 0;
+
+ assertEquals(1, a.value());
+ assert __version__() == 1;
+
+ assertEquals(2, a.value());
+ assert __version__() == 0;
+
+ assertEquals(1, a.value());
+ assert __version__() == 1;
+
+ assertEquals(2, a.value());
+ assert __version__() == 0;
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/methods/MethodReflectionTest.java b/dcevm/src/test/java/org/dcevm/test/methods/MethodReflectionTest.java
new file mode 100644
index 00000000..7c1eaaf7
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/methods/MethodReflectionTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.methods;
+
+import junit.framework.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.lang.reflect.Method;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Testing correct reflection functionality after class redefinition.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class MethodReflectionTest {
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ // Version 0
+ public static class A {
+
+ public int value() {
+ return 1;
+ }
+ }
+
+ public static class B extends A {
+
+ @Override
+ public int value() {
+ return 2;
+ }
+ }
+
+ public static class C extends A {
+
+ @Override
+ public int value() {
+ return 3;
+ }
+ }
+
+ // Version 1
+ public static class A___1 {
+
+ public int value() {
+ return 1;
+ }
+
+ public int value2() {
+ return 2;
+ }
+ }
+
+ // Version 2
+ public static class C___2 extends B {
+
+ @Override
+ public int value() {
+ return super.value();
+ }
+ }
+
+ @Test
+ public void testMethodReflection() {
+
+ assert __version__() == 0;
+
+ A a = new A();
+ B b = new B();
+ C c = new C();
+
+ assertEquals(1, a.value());
+ assertEquals(2, b.value());
+ assertEquals(3, c.value());
+
+ assertContainsMethod(A.class, "value");
+ assertDoesNotContainMethod(A.class, "value2");
+
+ __toVersion__(1);
+
+ assertEquals(1, a.value());
+ assertEquals(2, b.value());
+ assertEquals(3, c.value());
+
+ assertContainsMethod(A.class, "value");
+ assertContainsMethod(A.class, "value2");
+
+ __toVersion__(0);
+
+ assertEquals(1, a.value());
+ assertEquals(2, b.value());
+ assertEquals(3, c.value());
+
+ assertContainsMethod(A.class, "value");
+ assertDoesNotContainMethod(A.class, "value2");
+ }
+
+ private void assertContainsMethod(Class<?> c, String methodName) {
+ boolean found = false;
+ for (Method m : c.getDeclaredMethods()) {
+ if (m.getName().equals(methodName)) {
+ found = true;
+ break;
+ }
+ }
+
+ Assert.assertTrue(found);
+ }
+
+ private void assertDoesNotContainMethod(Class<?> c, String methodName) {
+ boolean found = false;
+ for (Method m : c.getDeclaredMethods()) {
+ if (m.getName().equals(methodName)) {
+ found = true;
+ break;
+ }
+ }
+
+ Assert.assertFalse(found);
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/methods/MethodsTestSuite.java b/dcevm/src/test/java/org/dcevm/test/methods/MethodsTestSuite.java
new file mode 100644
index 00000000..20888623
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/methods/MethodsTestSuite.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.methods;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * Class redefinition tests that perform adding/removing/changing the methods of a class.
+ *
+ * @author Thomas Wuerthinger
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ AddMethodTest.class,
+ DeleteActiveMethodTest.class,
+ ClassReflectionTest.class,
+ MethodReflectionTest.class,
+ ClassObjectSynchronizationTest.class,
+ ClassObjectHashcodeTest.class,
+ OverrideMethodTest.class,
+ SingleClassTest.class,
+ SingleClassReflectionTest.class,
+ AnnotationTest.class
+})
+public class MethodsTestSuite {
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/methods/OverrideMethodTest.java b/dcevm/src/test/java/org/dcevm/test/methods/OverrideMethodTest.java
new file mode 100644
index 00000000..dc98d608
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/methods/OverrideMethodTest.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.methods;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for the class relationship A<B<C with adding / removing methods.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class OverrideMethodTest {
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ // Version 0
+ public static class A {
+
+ public int value() {
+ return 5;
+ }
+ }
+
+ public static class B extends A {
+
+ public int doubled() {
+ return value() * 2;
+ }
+ }
+
+ public static class C extends B {
+ }
+
+ // Version 1
+ public static class A___1 {
+
+ public int value() {
+ return 10;
+ }
+ }
+
+ // Version 2
+ public static class B___2 extends A {
+
+ public int doubled() {
+ return value() * 3;
+ }
+ }
+
+ // Version 3
+ public static class C___3 extends B {
+
+ @Override
+ public int value() {
+ return 1;
+ }
+ }
+
+ // Verison 4
+ public static class A___4 {
+
+ public int value() {
+ return baseValue();
+ }
+
+ public int baseValue() {
+ return 20;
+ }
+ }
+
+ public static class B___4 extends A {
+
+ public int doubled() {
+ return value() * 2;
+ }
+ }
+
+ public static class C___4 extends B {
+ }
+
+ // Verison 5
+ public static class A___5 {
+
+ public int value() {
+ return baseValue();
+ }
+
+ public int baseValue() {
+ return 20;
+ }
+ }
+
+ @Test
+ public void testSimple() {
+
+ assert __version__() == 0;
+
+ A a = new A();
+ B b = new B();
+ C c = new C();
+
+ assertEquals(5, a.value());
+ assertEquals(5, b.value());
+ assertEquals(10, b.doubled());
+ assertEquals(5, c.value());
+ assertEquals(10, c.doubled());
+
+ __toVersion__(1);
+ assertEquals(10, a.value());
+ assertEquals(10, b.value());
+ assertEquals(20, b.doubled());
+ assertEquals(10, c.value());
+ assertEquals(20, c.doubled());
+
+ __toVersion__(2);
+ assertEquals(10, a.value());
+ assertEquals(10, b.value());
+ assertEquals(30, b.doubled());
+ assertEquals(10, c.value());
+ assertEquals(30, c.doubled());
+
+ __toVersion__(0);
+ assertEquals(5, a.value());
+ assertEquals(5, b.value());
+ assertEquals(10, b.doubled());
+ assertEquals(5, c.value());
+ assertEquals(10, c.doubled());
+ }
+
+ @Test
+ public void testMethodAdd() {
+
+ assert __version__() == 0;
+ A a = new A();
+ B b = new B();
+ C c = new C();
+
+ assertEquals(5, a.value());
+ assertEquals(5, b.value());
+ assertEquals(10, b.doubled());
+ assertEquals(5, c.value());
+ assertEquals(10, c.doubled());
+
+ __toVersion__(4);
+ assertEquals(20, a.value());
+ assertEquals(40, b.doubled());
+ assertEquals(20, b.value());
+ assertEquals(20, c.value());
+ assertEquals(40, c.doubled());
+
+ __toVersion__(0);
+ assertEquals(5, a.value());
+ assertEquals(5, b.value());
+ assertEquals(10, b.doubled());
+ assertEquals(5, c.value());
+ assertEquals(10, c.doubled());
+ }
+
+ @Test
+ public void testOverride() {
+
+ assert __version__() == 0;
+
+ A a = new A();
+ B b = new B();
+ C c = new C();
+
+ assertEquals(5, a.value());
+ assertEquals(5, b.value());
+ assertEquals(10, b.doubled());
+ assertEquals(5, c.value());
+ assertEquals(10, c.doubled());
+
+ __toVersion__(3);
+ assertEquals(5, a.value());
+ assertEquals(5, b.value());
+ assertEquals(10, b.doubled());
+ assertEquals(1, c.value());
+ assertEquals(2, c.doubled());
+
+ __toVersion__(0);
+ assertEquals(5, a.value());
+ assertEquals(5, b.value());
+ assertEquals(10, b.doubled());
+ assertEquals(5, c.value());
+ assertEquals(10, c.doubled());
+ }
+
+ @Test
+ public void testMethodAddAdvanced() {
+
+ assert __version__() == 0;
+ A a = new A();
+ B b = new B();
+ C c = new C();
+
+ assertEquals(5, a.value());
+ assertEquals(5, b.value());
+ assertEquals(10, b.doubled());
+ assertEquals(5, c.value());
+ assertEquals(10, c.doubled());
+
+ __toVersion__(5);
+ assertEquals(20, a.value());
+ assertEquals(20, b.value());
+ assertEquals(40, b.doubled());
+ assertEquals(20, c.value());
+ assertEquals(40, c.doubled());
+
+ __toVersion__(0);
+ assertEquals(5, a.value());
+ assertEquals(5, b.value());
+ assertEquals(10, b.doubled());
+ assertEquals(5, c.value());
+ assertEquals(10, c.doubled());
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/methods/SingleClassReflectionTest.java b/dcevm/src/test/java/org/dcevm/test/methods/SingleClassReflectionTest.java
new file mode 100644
index 00000000..61d3d31a
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/methods/SingleClassReflectionTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.methods;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Testing correct behaviour of the class object after class redefinition (with respect to the identity hash code and synchronization).
+ *
+ * @author Thomas Wuerthinger
+ */
+public class SingleClassReflectionTest {
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ // Version 0
+ public static class A {
+
+ public static synchronized void staticSynchronized() {
+ __toVersion__(1);
+ }
+ }
+
+
+ // Version 1
+ public static class A___1 {
+ public static synchronized void staticSynchronized() {
+ }
+ }
+
+
+ @Test
+ public void testHashcode() {
+
+ assert __version__() == 0;
+
+ A a = new A();
+
+ int hashcode = a.getClass().hashCode();
+
+ __toVersion__(1);
+
+ assertEquals(hashcode, a.getClass().hashCode());
+
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testStaticSynchronized() {
+
+ A.staticSynchronized();
+
+ assertEquals(1, __version__());
+
+ __toVersion__(0);
+ }
+
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/methods/SingleClassTest.java b/dcevm/src/test/java/org/dcevm/test/methods/SingleClassTest.java
new file mode 100644
index 00000000..4e12bc26
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/methods/SingleClassTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.methods;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for adding / removing methods in a single class.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class SingleClassTest {
+
+ // Version 0
+ public static class A {
+
+ public int value() {
+ return 5;
+ }
+ }
+
+ // Version 3
+ public static class A___3 {
+
+ public int value() {
+ return 5;
+ }
+ }
+
+ // Version 1
+ public static class A___1 {
+
+ public int value() {
+ return 6;
+ }
+
+ public int testValue() {
+ return 1;
+
+ }
+ }
+
+ // Version 2
+ public static class A___2 {
+
+ public int value() {
+ return baseValue() * 2;
+ }
+
+ public int baseValue() {
+ return 10;
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testSimpleReplacement() {
+
+ assert __version__() == 0;
+
+ A a = new A();
+
+ assertEquals(5, a.value());
+
+ __toVersion__(1);
+
+ assertEquals(6, a.value());
+
+ __toVersion__(3);
+
+ assertEquals(5, a.value());
+
+ __toVersion__(0);
+
+ assertEquals(5, a.value());
+ }
+
+ @Test
+ public void testAddMethod() {
+
+ assert __version__() == 0;
+
+ A a = new A();
+ assertEquals(a.value(), 5);
+
+ __toVersion__(2);
+ assertEquals(a.value(), 20);
+
+ __toVersion__(0);
+ assertEquals(a.value(), 5);
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/structural/AnonymousClassInMethodTest.java b/dcevm/src/test/java/org/dcevm/test/structural/AnonymousClassInMethodTest.java
new file mode 100644
index 00000000..5f923110
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/structural/AnonymousClassInMethodTest.java
@@ -0,0 +1,67 @@
+package org.dcevm.test.structural;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+
+/**
+ * Test insertion and swap of anonymous classes.
+ */
+public class AnonymousClassInMethodTest {
+
+ public static interface I {
+ public boolean m();
+ };
+
+ public static interface I2 {};
+
+ // Version 0
+ public static class A {
+ public boolean test() {
+ I anonymous = new I() {
+ @Override
+ public boolean m() {
+ return true;
+ }
+ };
+ return anonymous.m();
+ }
+ }
+
+ // Version 1
+ public static class A___1 {
+ public boolean test() {
+ I2 insertedAnonymous = new I2() {};
+
+ I anonymous = new I() {
+ @Override
+ public boolean m() {
+ return false;
+ }
+ };
+ return anonymous.m();
+ }
+ }
+
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ // TODO this test fails, because conent of A$1 is now interface I2 instead of interface I (not compatible change)
+ // HotswapAgent plugin AnonymousClassPatch solves this on Java instrumentation level by exchanging content of class files.
+ // @see https://github.com/HotswapProjects/HotswapAgent/tree/master/HotswapAgent/src/main/java/org/hotswap/agent/plugin/jvm
+ //@Test
+ public void testAnonymous() {
+ assert __version__() == 0;
+ Assert.assertTrue(new A().test());
+ __toVersion__(1);
+ Assert.assertFalse(new A().test());
+ __toVersion__(0);
+ Assert.assertTrue(new A().test());
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/structural/InterfaceTest.java b/dcevm/src/test/java/org/dcevm/test/structural/InterfaceTest.java
new file mode 100644
index 00000000..1a089965
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/structural/InterfaceTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.structural;
+
+import org.dcevm.test.TestUtil;
+import org.junit.*;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.*;
+
+/**
+ * Tests for adding an interface to a class and for changing the methods of an interface.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class InterfaceTest {
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ public static interface A {
+
+ int giveMeFive();
+ }
+
+ public static class AImpl {
+
+ public int giveMeFive() {
+ return 5;
+ }
+ }
+
+ public static class BImpl implements A {
+
+ @Override
+ public int giveMeFive() {
+ return 5;
+ }
+
+ public int giveMeTen() {
+ return 10;
+ }
+ }
+
+ public static class AImpl___1 implements A {
+
+ @Override
+ public int giveMeFive() {
+ return 5;
+ }
+ }
+
+ public static interface A___2 {
+
+ int giveMeTen();
+ }
+
+ public static class Helper {
+
+ public int giveMeTenA2(A a) {
+ return 3;
+ }
+ }
+
+ public static class Helper___2 {
+
+ public int giveMeTenA2(A a) {
+ return ((A___2) a).giveMeTen();
+ }
+ }
+
+ @Test
+ public void testAddInterface() {
+
+ modifyInterface();
+ assert __version__() == 0;
+
+ AImpl a = new AImpl();
+ assertFalse(a instanceof A);
+ try {
+ int val = (((A) a).giveMeFive());
+ fail();
+ } catch (ClassCastException e) {
+ }
+
+ __toVersion__(1);
+ assertTrue(a instanceof A);
+ assertEquals(5, ((A) a).giveMeFive());
+
+ TestUtil.assertUnsupportedToVersionWithLight(InterfaceTest.class, 0);
+ }
+
+ public void modifyInterface() {
+
+ assert __version__() == 0;
+
+ BImpl b = new BImpl();
+ assertTrue(b instanceof A);
+
+ __toVersion__(2);
+
+ assertEquals(10, new Helper().giveMeTenA2(b));
+
+ __toVersion__(0);
+ assertEquals(5, ((A) b).giveMeFive());
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/structural/RedefineClassClassTest.java b/dcevm/src/test/java/org/dcevm/test/structural/RedefineClassClassTest.java
new file mode 100644
index 00000000..e0da9002
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/structural/RedefineClassClassTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package org.dcevm.test.structural;
+
+import org.dcevm.ClassRedefinitionPolicy;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+
+/**
+ * Smallest test case for redefining the interface java/lang/reflect/Type (causes java/lang/Class being redefined)
+ *
+ * @author Thomas Wuerthinger
+ */
+@Ignore
+public class RedefineClassClassTest {
+
+ // Version 0
+ public interface Type {
+ }
+
+ // Version 1
+ @ClassRedefinitionPolicy(alias = java.lang.reflect.Type.class)
+ public interface Type___1 {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testRedefineClass() {
+
+ assert __version__() == 0;
+
+ __toVersion__(1);
+
+ __toVersion__(0);
+
+ __toVersion__(1);
+
+ __toVersion__(0);
+
+
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/structural/RedefineObjectClassTest.java b/dcevm/src/test/java/org/dcevm/test/structural/RedefineObjectClassTest.java
new file mode 100644
index 00000000..08d07c1a
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/structural/RedefineObjectClassTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package org.dcevm.test.structural;
+
+import org.dcevm.ClassRedefinitionPolicy;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Smallest test case for redefining java/lang/Object, without changing the number of virtual methods.
+ *
+ * @author Thomas Wuerthinger
+ */
+@Ignore
+public class RedefineObjectClassTest {
+
+ // Version 0
+ public static class Helper {
+ public static String access(Object o) {
+ return "";
+ }
+ }
+
+ // Version 1
+
+ public static class Helper___1 {
+ public static String access(Object o) {
+ return ((A___1) o).myTestFunction___();
+ }
+ }
+
+ @ClassRedefinitionPolicy(alias = java.lang.Object.class)
+ public static class A___1 {
+
+ public final native Class<? extends Object> getClass___();
+
+ @Override
+ public native int hashCode();
+
+ @Override
+ public boolean equals(Object obj) {
+ return (this == obj);
+ }
+
+ public static int x;
+ public static int x1;
+ public static int x2;
+ public static int x3;
+ public static int x4;
+ public static int x5;
+
+ @Override
+ protected native Object clone() throws CloneNotSupportedException;
+
+ @Override
+ public String toString() {
+ System.out.println("x=" + (x++));
+ return getClass().getName() + "@" + Integer.toHexString(hashCode());// myTestFunction___();
+ }
+
+ public final String myTestFunction___() {
+ return "org/dcevm/test";
+ }
+
+ public final native void notify___();
+
+ public final native void notifyAll___();
+
+ public final native void wait___(long timeout) throws InterruptedException;
+
+ public final void wait___(long timeout, int nanos) throws InterruptedException {
+
+
+ if (timeout < 0) {
+ throw new IllegalArgumentException("timeout value is negative");
+ }
+
+ if (nanos < 0 || nanos > 999999) {
+ throw new IllegalArgumentException(
+ "nanosecond timeout value out of range");
+ }
+
+ if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {
+ timeout++;
+ }
+
+ wait(timeout);
+ }
+
+ public final void wait___() throws InterruptedException {
+ wait(0);
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testRedefineObject() {
+
+ assert __version__() == 0;
+
+ Object o = new Object();
+ __toVersion__(1);
+
+ System.out.println(this.toString());
+ System.out.println(o.toString());
+ System.out.println(this.toString());
+
+
+ //assertEquals("test", o.toString());
+ assertEquals("org/dcevm/test", Helper.access(o));
+ __toVersion__(0);
+ __toVersion__(1);
+ __toVersion__(0);
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/structural/StructuralTestSuite.java b/dcevm/src/test/java/org/dcevm/test/structural/StructuralTestSuite.java
new file mode 100644
index 00000000..633ba059
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/structural/StructuralTestSuite.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.structural;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * Class redefinition tests that do arbitrary structural changes.
+ * <p/>
+ * TODO: Add a test where redefinition triggers classloading (e.g. because a super type is not yet loaded).
+ *
+ * @author Thomas Wuerthinger
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ RedefineClassClassTest.class,
+ RedefineObjectClassTest.class,
+ InterfaceTest.class,
+ ThisTypeChange.class
+})
+public class StructuralTestSuite {
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/structural/ThisTypeChange.java b/dcevm/src/test/java/org/dcevm/test/structural/ThisTypeChange.java
new file mode 100644
index 00000000..9cfde217
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/structural/ThisTypeChange.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.structural;
+
+import org.dcevm.test.TestUtil;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+
+/**
+ * Tests that change the type of the object references by the Java this pointer.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class ThisTypeChange {
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ // Version 0
+ public static class A {
+
+ public int valueOK() {
+ return 1;
+ }
+
+ public int value() {
+ __toVersion__(1);
+ return 1;
+ }
+ }
+
+ public static class B extends A {
+
+ @Override
+ public int value() {
+ return super.value();
+ }
+
+
+ @Override
+ public int valueOK() {
+ __toVersion__(1);
+ return super.valueOK();
+ }
+ }
+
+ // Version 1
+ public static class A___1 {
+
+ public int valueOK() {
+ return 2;
+ }
+ }
+
+ // Version 1
+ public static class B___1 {
+ }
+
+ // Method to enforce cast (otherwise bytecodes become invalid in version 2)
+ public static A convertBtoA(Object b) {
+ return (A) b;
+ }
+
+ @Test
+ public void testThisTypeChange() {
+
+ assert __version__() == 0;
+
+ final B b = new B();
+ TestUtil.assertUnsupported(new Runnable() {
+ @Override
+ public void run() {
+ b.value();
+ }
+ });
+
+ assert __version__() == 0;
+
+ TestUtil.assertUnsupported(new Runnable() {
+ @Override
+ public void run() {
+ b.valueOK();
+ }
+ });
+
+ assert __version__() == 0;
+
+ TestUtil.assertUnsupported(new Runnable() {
+ @Override
+ public void run() {
+ b.valueOK();
+ }
+ });
+
+ assert __version__() == 0;
+ }
+}
diff --git a/dcevm/src/test/java/org/dcevm/test/util/HotSwapTestHelper.java b/dcevm/src/test/java/org/dcevm/test/util/HotSwapTestHelper.java
new file mode 100644
index 00000000..5ecbd83e
--- /dev/null
+++ b/dcevm/src/test/java/org/dcevm/test/util/HotSwapTestHelper.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package org.dcevm.test.util;
+
+import org.dcevm.HotSwapTool;
+
+/**
+ * Shortcut methods for testing. Methods are named this way to make them more visible in the test code.
+ * @author Ivan Dubrov
+ */
+public class HotSwapTestHelper {
+ /**
+ * Returns the current version of the inner classes of an outer class.
+ * <p/>
+ * Caller class is used as an outer class.
+ *
+ * @return the version of the inner classes of the outer class
+ */
+ public static int __version__() {
+ return HotSwapTool.getCurrentVersion(determineOuter(0));
+ }
+
+ /**
+ * Redefines all inner classes of a outer class to a specified version. Inner classes who do not have a particular
+ * representation for a version remain unchanged.
+ * <p/>
+ * Caller class is used as an outer class.
+ *
+ * @param versionNumber the target version number
+ */
+ public static void __toVersion__(int versionNumber) {
+ HotSwapTool.toVersion(determineOuter(0), versionNumber);
+ }
+
+ /**
+ * Helper method to determine caller outer class.
+ * <p/>
+ * Takes caller class and finds its top enclosing class (which is supposed to be test class).
+ *
+ * @param level on which level this call is being made. 0 - call is made immediately in the method of HotSwapTool.
+ * @return outer class reference
+ */
+ private static Class<?> determineOuter(int level) {
+ StackTraceElement[] stack = Thread.currentThread().getStackTrace();
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ // one for Thread#getStackTrace
+ // one for #determineOuter
+ // one for the caller
+ String callerName = stack[level + 3].getClassName();
+ try {
+ Class<?> clazz = cl.loadClass(callerName);
+ while (clazz.getEnclosingClass() != null) {
+ clazz = clazz.getEnclosingClass();
+ }
+ return clazz;
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException("Cannot find caller class: " + callerName, e);
+ }
+ }
+}
diff --git a/dcevm/src/test/java8/org/dcevm/test/methods/DefaultMethodsTest.java b/dcevm/src/test/java8/org/dcevm/test/methods/DefaultMethodsTest.java
new file mode 100644
index 00000000..de6b3c64
--- /dev/null
+++ b/dcevm/src/test/java8/org/dcevm/test/methods/DefaultMethodsTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.dcevm.test.methods;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.dcevm.test.util.HotSwapTestHelper.__version__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for the class relationship A<B<C with adding / removing methods.
+ *
+ * @author Thomas Wuerthinger
+ */
+public class DefaultMethodsTest {
+
+ @Before
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ // Version 0
+ public static interface A {
+ default int value() {
+ __toVersion__(1);
+ return 1 + value();
+ }
+ }
+
+ public static class B implements A {
+ }
+
+ public static interface C {
+ int value();
+ }
+
+ public static class D implements C {
+ @Override
+ public int value() {
+ __toVersion__(2);
+ return 3 + value();
+ }
+ }
+
+ // Version 1
+ public static interface A___1 {
+ int value();
+ }
+
+
+ public static class B___1 implements A {
+ public int value() {
+ return 2;
+ }
+ }
+
+ // Version 2
+ public static interface C___2 {
+ default int value() {
+ return 5;
+ }
+ }
+
+ public static class D___2 implements C___2 {
+ }
+
+ @Test
+ public void testDefaultMethodReplacedWithInstance() {
+ assert __version__() == 0;
+
+ A a = new B();
+ assertEquals(3, a.value());
+
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testInstanceMethodReplacedWithDefault() {
+ assert __version__() == 0;
+
+ C c = new D();
+ assertEquals(8, c.value());
+
+ __toVersion__(0);
+ }
+}
diff --git a/dcevm/src/test/java8/org/dcevm/test/util/HotSwapTestHelper.java b/dcevm/src/test/java8/org/dcevm/test/util/HotSwapTestHelper.java
new file mode 100644
index 00000000..5ecbd83e
--- /dev/null
+++ b/dcevm/src/test/java8/org/dcevm/test/util/HotSwapTestHelper.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+package org.dcevm.test.util;
+
+import org.dcevm.HotSwapTool;
+
+/**
+ * Shortcut methods for testing. Methods are named this way to make them more visible in the test code.
+ * @author Ivan Dubrov
+ */
+public class HotSwapTestHelper {
+ /**
+ * Returns the current version of the inner classes of an outer class.
+ * <p/>
+ * Caller class is used as an outer class.
+ *
+ * @return the version of the inner classes of the outer class
+ */
+ public static int __version__() {
+ return HotSwapTool.getCurrentVersion(determineOuter(0));
+ }
+
+ /**
+ * Redefines all inner classes of a outer class to a specified version. Inner classes who do not have a particular
+ * representation for a version remain unchanged.
+ * <p/>
+ * Caller class is used as an outer class.
+ *
+ * @param versionNumber the target version number
+ */
+ public static void __toVersion__(int versionNumber) {
+ HotSwapTool.toVersion(determineOuter(0), versionNumber);
+ }
+
+ /**
+ * Helper method to determine caller outer class.
+ * <p/>
+ * Takes caller class and finds its top enclosing class (which is supposed to be test class).
+ *
+ * @param level on which level this call is being made. 0 - call is made immediately in the method of HotSwapTool.
+ * @return outer class reference
+ */
+ private static Class<?> determineOuter(int level) {
+ StackTraceElement[] stack = Thread.currentThread().getStackTrace();
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ // one for Thread#getStackTrace
+ // one for #determineOuter
+ // one for the caller
+ String callerName = stack[level + 3].getClassName();
+ try {
+ Class<?> clazz = cl.loadClass(callerName);
+ while (clazz.getEnclosingClass() != null) {
+ clazz = clazz.getEnclosingClass();
+ }
+ return clazz;
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException("Cannot find caller class: " + callerName, e);
+ }
+ }
+}