Making DCEVM to be toplevel project that clones HotSpot repository, patches the code, builds JVM and tests it.tags/light-jdk8u5+36
@@ -0,0 +1,5 @@ | |||
/.gradle | |||
/.idea | |||
/hotspot | |||
build | |||
*.iml |
@@ -0,0 +1,4 @@ | |||
Manifest-Version: 1.0 | |||
Can-Redefine-Classes: true | |||
Agent-Class: org.dcevm.agent.InstrumentationAgent | |||
Premain-Class: org.dcevm.agent.InstrumentationAgent |
@@ -0,0 +1,18 @@ | |||
package org.dcevm.agent; | |||
import java.lang.instrument.Instrumentation; | |||
/** | |||
* Simple agent to get access to the Instrumentation API. | |||
*/ | |||
public class InstrumentationAgent { | |||
public static Instrumentation INSTRUMENTATION; | |||
public static void agentmain(String args, Instrumentation instr) { | |||
INSTRUMENTATION = instr; | |||
} | |||
public static void premain(String args, Instrumentation instr) { | |||
INSTRUMENTATION = instr; | |||
} | |||
} |
@@ -0,0 +1,8 @@ | |||
set WINDOWS_SDK=c:\Program Files\Microsoft SDKs\Windows\v7.1 | |||
call "%WINDOWS_SDK%\bin\setenv.cmd" /%ARCH% | |||
echo Script arguments: %* | |||
set CYGWIN=C:\cygwin | |||
set SCRIPT=%~dp0 | |||
set HOTSPOTWORKSPACE=. | |||
%CYGWIN%\bin\bash --login -c 'cd `/usr/bin/cygpath "$SCRIPT"/..` ; /usr/bin/pwd ; /usr/bin/make -C "make" %*' |
@@ -0,0 +1,223 @@ | |||
// Global settings | |||
project.ext { | |||
// Source JRE used for compilation, etc | |||
if (!project.hasProperty('jre')) { | |||
jre = System.getProperty('java.home') | |||
} | |||
os = Os.current() | |||
arch = Arch.current() | |||
if (!project.hasProperty('targetJre')) { | |||
targetJre = jre | |||
} | |||
} | |||
def targetJreFile = file(targetJre) | |||
def jreFile = file(jre) | |||
// HotSpot itself | |||
project('hotspot') { | |||
task clean(type: InvokeMake) { | |||
args 'clean' | |||
} | |||
task prepareJvm { | |||
onlyIf { jreFile != targetJreFile } | |||
doLast { | |||
ant.copy(todir: targetJreFile) { | |||
fileset(dir: jreFile) | |||
} | |||
ant.chmod(file: new File(targetJreFile, 'bin/java'), perm: '0755') | |||
} | |||
} | |||
task clone(description: 'Clone HotSpot repository') { | |||
onlyIf { !file('hotspot').exists() } | |||
doLast { | |||
exec { | |||
workingDir '..' | |||
executable 'hg' | |||
args 'clone', hotspotRepository | |||
} | |||
} | |||
} | |||
task patch(description: 'Patch HotSpot sources', dependsOn: clone) << { | |||
exec { | |||
executable 'hg' | |||
args 'pull' | |||
} | |||
exec { | |||
executable 'hg' | |||
args 'update', '-C', '-r', hotspotTag | |||
} | |||
new ByteArrayOutputStream().withStream { os -> | |||
exec { | |||
workingDir 'hotspot' | |||
executable 'hg' | |||
args 'status' | |||
standardOutput os | |||
} | |||
def str = os.toString() | |||
def matcher = str =~ /(?m)^\?\s+(.*)$/ | |||
matcher.each { | |||
ant.delete(file: new File(file('hotspot'), it[1])) | |||
} | |||
} | |||
ant.patch(patchfile: "../patches/dcevm-${hotspotTag}.patch", strip: 1) | |||
} | |||
task compileFastdebug(type: InvokeMake) { | |||
args 'STRIP_POLICY=no_strip' | |||
args 'ZIP_DEBUGINFO_FILES=0' | |||
args 'ENABLE_FULL_DEBUG_SYMBOLS=1' | |||
args 'fastdebug' | |||
} | |||
task compileProduct(type: InvokeMake) { | |||
args 'ENABLE_FULL_DEBUG_SYMBOLS=0' | |||
args 'product' | |||
} | |||
compileFastdebug.mustRunAfter patch | |||
compileProduct.mustRunAfter patch | |||
// Install given kind of DCEVM into destination JRE | |||
['Product', 'Fastdebug'].each { k -> | |||
task("install${k}", dependsOn: [prepareJvm, "compile${k}"]) << { | |||
def installPath = new File(new File(targetJreFile, arch == Arch.X86 ? os.installPath32 : os.installPath64), jvmName) | |||
logger.info("Installing DCEVM runtime into JRE with JVM name '${jvmName}' and kind '${k.toLowerCase()}' at ${installPath}") | |||
ant.copy(todir: installPath, overwrite: true) { | |||
fileset(dir: "build/${os.buildPath}/${os.buildPath}_${arch.buildArch}_${compiler}/${k.toLowerCase()}", | |||
includes: 'libjvm.so,libjsig.so,jvm.dll,jsig.dll,libjvm.dylib,libjsig.dylib') | |||
} | |||
} | |||
} | |||
} | |||
// Java projects for testing DCEVM | |||
def setup(prjs, closure) { | |||
prjs.each { prj -> | |||
project(prj, closure) | |||
} | |||
} | |||
setup(['agent', 'framework', 'tests-java7', 'tests-java8'], { | |||
apply plugin: 'java' | |||
apply plugin: 'idea' | |||
repositories { | |||
mavenCentral() | |||
} | |||
}) | |||
project('agent') { | |||
jar { | |||
manifest { | |||
from "src/main/java/META-INF/MANIFEST.MF" | |||
} | |||
} | |||
} | |||
project('framework') { | |||
dependencies { | |||
compile project(':agent') | |||
compile group: 'asm', name: 'asm-all', version: '3.3.+' | |||
compile files(System.getProperty("java.home") + '/../lib/tools.jar') | |||
} | |||
} | |||
project('tests-java8') { | |||
sourceCompatibility = 1.8 | |||
targetCompatibility = 1.8 | |||
} | |||
setup(['tests-java7', 'tests-java8'], { | |||
dependencies { | |||
compile project(':framework') | |||
testCompile group: 'junit', name: 'junit', version: '4.11' | |||
} | |||
test { | |||
executable new File(targetJreFile, 'bin/java') | |||
jvmArgs "-XXaltjvm=${jvmName}" | |||
jvmArgs '-javaagent:../agent/build/libs/agent.jar' | |||
if (arch == Arch.X86_64) { | |||
jvmArgs(project.oops == "compressed" ? '-XX:+UseCompressedOops' : "-XX:-UseCompressedOops") | |||
} | |||
jvmArgs "-XX:TraceRedefineClasses=${traceRedefinition}" | |||
ignoreFailures = true | |||
outputs.upToDateWhen { false } | |||
} | |||
test.dependsOn project(':hotspot').tasks[kind == 'fastdebug' ? 'installFastdebug' : 'installProduct'] | |||
}) | |||
enum Arch { | |||
X86(["i386", "i486", "i586", "x86"], 'i486', 32), | |||
X86_64(["x86_64", "x64", "amd64"], 'amd64', 64) | |||
final List<String> names | |||
final String buildArch | |||
final int bits | |||
Arch(List<String> names, String buildArch, int bits) { | |||
this.names = names | |||
this.buildArch = buildArch | |||
this.bits = bits | |||
} | |||
static Arch find(String token) { | |||
Arch res = values().find({ v -> v.names.contains(token) }) | |||
return res | |||
} | |||
static Arch current() { | |||
return find(System.getProperty("os.arch")) | |||
} | |||
} | |||
enum Os { | |||
MAC('bsd', 'lib', 'lib'), | |||
WINDOWS('windows', 'bin', 'bin'), | |||
UNIX('linux', 'lib/i386', 'lib/amd64') | |||
final String buildPath; | |||
final String installPath32; | |||
final String installPath64; | |||
Os(String buildPath, String installPath32, String installPath64) { | |||
this.buildPath = buildPath | |||
this.installPath32 = installPath32 | |||
this.installPath64 = installPath64 | |||
} | |||
static Os current() { | |||
return values().find { os -> org.apache.tools.ant.taskdefs.condition.Os.isFamily(os.name().toLowerCase()) } | |||
} | |||
} | |||
// Helper task to run make targets against hotspot | |||
class InvokeMake extends org.gradle.api.tasks.Exec { | |||
InvokeMake() { | |||
logging.captureStandardOutput LogLevel.INFO | |||
if (project.rootProject.os != Os.WINDOWS) { | |||
commandLine 'make', '-C', 'make' | |||
} else { | |||
// Using launcher script | |||
commandLine 'cmd', '/c', '..\\build.cmd' | |||
environment ARCH: project.rootProject.arch == Arch.X86 ? 'x86' : 'x64' | |||
} | |||
args 'OPENJDK=true' | |||
args "HOTSPOT_BUILD_VERSION=dcevmlight-${project.rootProject.buildNumber}" | |||
args "ARCH_DATA_MODEL=${project.rootProject.arch.bits}" | |||
args "ALT_BOOTDIR=${project.rootProject.jre.replace('\\', '/')}/.." | |||
// Replacing backslashes is essential for Windows! | |||
args 'COMPILER_WARNINGS_FATAL=false' // Clang is very serious about warnings | |||
args 'HOTSPOT_BUILD_JOBS=4' | |||
} | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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. | |||
} | |||
} |
@@ -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 + "'" ); | |||
} | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} | |||
} | |||
@@ -0,0 +1,28 @@ | |||
# Default settings for DCEVM build/testing | |||
traceRedefinition=1 | |||
# Which JVM kind to use for testing, fastdebug (produces better crash reports) or product (faster). | |||
kind=fastdebug | |||
# If should use compressed oops (-XX:+UseCompressedOops) or not for testing. | |||
oops=compressed | |||
# DCEVM build number | |||
buildNumber=dev | |||
# Name of JVM to install DCEVM to. Specifx -XXaltjvm=<jvmName> to run given JVM. | |||
jvmName=dcevm | |||
# Which flavor of compiler to use. Leave default value. | |||
compiler=compiler2 | |||
# Path to install JRE. | |||
# Used when creating local version of JRE with DCEVM library installed. | |||
targetJre=build/jre | |||
# Tag to base DCEVM on | |||
hotspotTag=jdk8u5-b13 | |||
# Repository to clone hotspot from | |||
hotspotRepository=http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot | |||
#hotspotRepository=http://hg.openjdk.java.net/jdk7u/jdk7u/hotspot |
@@ -0,0 +1,6 @@ | |||
#Thu Apr 24 15:01:45 PDT 2014 | |||
distributionBase=GRADLE_USER_HOME | |||
distributionPath=wrapper/dists | |||
zipStoreBase=GRADLE_USER_HOME | |||
zipStorePath=wrapper/dists | |||
distributionUrl=http\://services.gradle.org/distributions/gradle-1.11-all.zip |
@@ -0,0 +1,164 @@ | |||
#!/usr/bin/env bash | |||
############################################################################## | |||
## | |||
## Gradle start up script for UN*X | |||
## | |||
############################################################################## | |||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | |||
DEFAULT_JVM_OPTS="" | |||
APP_NAME="Gradle" | |||
APP_BASE_NAME=`basename "$0"` | |||
# Use the maximum available, or set MAX_FD != -1 to use that value. | |||
MAX_FD="maximum" | |||
warn ( ) { | |||
echo "$*" | |||
} | |||
die ( ) { | |||
echo | |||
echo "$*" | |||
echo | |||
exit 1 | |||
} | |||
# OS specific support (must be 'true' or 'false'). | |||
cygwin=false | |||
msys=false | |||
darwin=false | |||
case "`uname`" in | |||
CYGWIN* ) | |||
cygwin=true | |||
;; | |||
Darwin* ) | |||
darwin=true | |||
;; | |||
MINGW* ) | |||
msys=true | |||
;; | |||
esac | |||
# For Cygwin, ensure paths are in UNIX format before anything is touched. | |||
if $cygwin ; then | |||
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` | |||
fi | |||
# Attempt to set APP_HOME | |||
# Resolve links: $0 may be a link | |||
PRG="$0" | |||
# Need this for relative symlinks. | |||
while [ -h "$PRG" ] ; do | |||
ls=`ls -ld "$PRG"` | |||
link=`expr "$ls" : '.*-> \(.*\)$'` | |||
if expr "$link" : '/.*' > /dev/null; then | |||
PRG="$link" | |||
else | |||
PRG=`dirname "$PRG"`"/$link" | |||
fi | |||
done | |||
SAVED="`pwd`" | |||
cd "`dirname \"$PRG\"`/" >&- | |||
APP_HOME="`pwd -P`" | |||
cd "$SAVED" >&- | |||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar | |||
# Determine the Java command to use to start the JVM. | |||
if [ -n "$JAVA_HOME" ] ; then | |||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then | |||
# IBM's JDK on AIX uses strange locations for the executables | |||
JAVACMD="$JAVA_HOME/jre/sh/java" | |||
else | |||
JAVACMD="$JAVA_HOME/bin/java" | |||
fi | |||
if [ ! -x "$JAVACMD" ] ; then | |||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME | |||
Please set the JAVA_HOME variable in your environment to match the | |||
location of your Java installation." | |||
fi | |||
else | |||
JAVACMD="java" | |||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | |||
Please set the JAVA_HOME variable in your environment to match the | |||
location of your Java installation." | |||
fi | |||
# Increase the maximum file descriptors if we can. | |||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then | |||
MAX_FD_LIMIT=`ulimit -H -n` | |||
if [ $? -eq 0 ] ; then | |||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then | |||
MAX_FD="$MAX_FD_LIMIT" | |||
fi | |||
ulimit -n $MAX_FD | |||
if [ $? -ne 0 ] ; then | |||
warn "Could not set maximum file descriptor limit: $MAX_FD" | |||
fi | |||
else | |||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" | |||
fi | |||
fi | |||
# For Darwin, add options to specify how the application appears in the dock | |||
if $darwin; then | |||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" | |||
fi | |||
# For Cygwin, switch paths to Windows format before running java | |||
if $cygwin ; then | |||
APP_HOME=`cygpath --path --mixed "$APP_HOME"` | |||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` | |||
# We build the pattern for arguments to be converted via cygpath | |||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` | |||
SEP="" | |||
for dir in $ROOTDIRSRAW ; do | |||
ROOTDIRS="$ROOTDIRS$SEP$dir" | |||
SEP="|" | |||
done | |||
OURCYGPATTERN="(^($ROOTDIRS))" | |||
# Add a user-defined pattern to the cygpath arguments | |||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then | |||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" | |||
fi | |||
# Now convert the arguments - kludge to limit ourselves to /bin/sh | |||
i=0 | |||
for arg in "$@" ; do | |||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` | |||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option | |||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition | |||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` | |||
else | |||
eval `echo args$i`="\"$arg\"" | |||
fi | |||
i=$((i+1)) | |||
done | |||
case $i in | |||
(0) set -- ;; | |||
(1) set -- "$args0" ;; | |||
(2) set -- "$args0" "$args1" ;; | |||
(3) set -- "$args0" "$args1" "$args2" ;; | |||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;; | |||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; | |||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; | |||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; | |||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; | |||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; | |||
esac | |||
fi | |||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules | |||
function splitJvmOpts() { | |||
JVM_OPTS=("$@") | |||
} | |||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS | |||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" | |||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" |
@@ -0,0 +1,90 @@ | |||
@if "%DEBUG%" == "" @echo off | |||
@rem ########################################################################## | |||
@rem | |||
@rem Gradle startup script for Windows | |||
@rem | |||
@rem ########################################################################## | |||
@rem Set local scope for the variables with windows NT shell | |||
if "%OS%"=="Windows_NT" setlocal | |||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | |||
set DEFAULT_JVM_OPTS= | |||
set DIRNAME=%~dp0 | |||
if "%DIRNAME%" == "" set DIRNAME=. | |||
set APP_BASE_NAME=%~n0 | |||
set APP_HOME=%DIRNAME% | |||
@rem Find java.exe | |||
if defined JAVA_HOME goto findJavaFromJavaHome | |||
set JAVA_EXE=java.exe | |||
%JAVA_EXE% -version >NUL 2>&1 | |||
if "%ERRORLEVEL%" == "0" goto init | |||
echo. | |||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | |||
echo. | |||
echo Please set the JAVA_HOME variable in your environment to match the | |||
echo location of your Java installation. | |||
goto fail | |||
:findJavaFromJavaHome | |||
set JAVA_HOME=%JAVA_HOME:"=% | |||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe | |||
if exist "%JAVA_EXE%" goto init | |||
echo. | |||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% | |||
echo. | |||
echo Please set the JAVA_HOME variable in your environment to match the | |||
echo location of your Java installation. | |||
goto fail | |||
:init | |||
@rem Get command-line arguments, handling Windowz variants | |||
if not "%OS%" == "Windows_NT" goto win9xME_args | |||
if "%@eval[2+2]" == "4" goto 4NT_args | |||
:win9xME_args | |||
@rem Slurp the command line arguments. | |||
set CMD_LINE_ARGS= | |||
set _SKIP=2 | |||
:win9xME_args_slurp | |||
if "x%~1" == "x" goto execute | |||
set CMD_LINE_ARGS=%* | |||
goto execute | |||
:4NT_args | |||
@rem Get arguments from the 4NT Shell from JP Software | |||
set CMD_LINE_ARGS=%$ | |||
:execute | |||
@rem Setup the command line | |||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar | |||
@rem Execute Gradle | |||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% | |||
:end | |||
@rem End local scope for the variables with windows NT shell | |||
if "%ERRORLEVEL%"=="0" goto mainEnd | |||
:fail | |||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of | |||
rem the _cmd.exe /c_ return code! | |||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 | |||
exit /b 1 | |||
:mainEnd | |||
if "%OS%"=="Windows_NT" endlocal | |||
:omega |
@@ -0,0 +1,174 @@ | |||
/* | |||
* 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. | |||
* | |||
*/ | |||
#include <stdio.h> | |||
#include <jni.h> | |||
#include <string.h> | |||
#include <stdlib.h> | |||
#include "natives.h" | |||
JNIEXPORT jint JNICALL Java_at_ssw_hotswap_test_natives_SimpleNativeTest_00024A_value(JNIEnv *env, jclass c) { | |||
return 1; | |||
} | |||
JNIEXPORT jint JNICALL Java_at_ssw_hotswap_test_natives_SimpleNativeTest_00024A_value2(JNIEnv *env, jclass c) { | |||
return 2; | |||
} | |||
JNIEXPORT jclass JNICALL Java_at_ssw_hotswap_test_access_jni_JNIVMAccess_findClassNative(JNIEnv *env, jclass c, jstring s) { | |||
const char* name = (*env)->GetStringUTFChars(env, s, 0); | |||
jclass clazz = (*env)->FindClass(env, name); | |||
(*env)->ReleaseStringUTFChars(env, s, name); | |||
return clazz; | |||
} | |||
JNIEXPORT jobject JNICALL Java_at_ssw_hotswap_test_access_jni_JNIClassAccess_findMethodNative(JNIEnv *env, jclass c, jclass cls, jstring methodName) { | |||
const char *methodstr = (*env)->GetStringUTFChars(env, methodName, 0); | |||
jclass jCls = (*env)->GetObjectClass(env, cls); | |||
// Get Method ID of getMethods() | |||
jmethodID midGetFields = (*env)->GetMethodID(env, jCls, "getDeclaredMethods", "()[Ljava/lang/reflect/Method;"); | |||
(*env)->ExceptionDescribe(env); | |||
jobjectArray jobjArray = (jobjectArray) (*env)->CallObjectMethod(env, cls, midGetFields); | |||
jsize len = (*env)->GetArrayLength(env, jobjArray); | |||
jsize i = 0; | |||
for (i = 0; i < len; i++) { | |||
jobject _strMethod = (*env)->GetObjectArrayElement(env, jobjArray, i); | |||
jclass _methodClazz = (*env)->GetObjectClass(env, _strMethod); | |||
jmethodID mid = (*env)->GetMethodID(env, _methodClazz, "getName", "()Ljava/lang/String;"); | |||
jstring _name = (jstring) (*env)->CallObjectMethod(env, _strMethod, mid); | |||
const char *str = (*env)->GetStringUTFChars(env, _name, 0); | |||
if (strcmp(str, methodstr) == 0) { | |||
(*env)->ReleaseStringUTFChars(env, methodName, methodstr); | |||
(*env)->ReleaseStringUTFChars(env, _name, str); | |||
return _strMethod; | |||
} | |||
(*env)->ReleaseStringUTFChars(env, _name, str); | |||
} | |||
jclass exc = (*env)->FindClass(env, "java/lang/NoSuchMethodError"); | |||
(*env)->ThrowNew(env, exc, methodstr); | |||
(*env)->ReleaseStringUTFChars(env, methodName, methodstr); | |||
} | |||
JNIEXPORT jobjectArray JNICALL Java_at_ssw_hotswap_test_access_jni_JNIClassAccess_getMethodsNative(JNIEnv *env, jclass c, jclass cls) { | |||
jobjectArray array; | |||
jclass jCls = (*env)->GetObjectClass(env, cls); | |||
// Get Method ID of getMethods() | |||
jmethodID midGetFields = (*env)->GetMethodID(env, jCls, "getDeclaredMethods", "()[Ljava/lang/reflect/Method;"); | |||
(*env)->ExceptionDescribe(env); | |||
jobjectArray jobjArray = (jobjectArray) (*env)->CallObjectMethod(env, cls, midGetFields); | |||
jsize len = (*env)->GetArrayLength(env, jobjArray); | |||
jsize i = 0; | |||
array = (*env)->NewObjectArray(env, len, (*env)->FindClass(env, "java/lang/reflect/Method"), 0); | |||
for (i = 0; i < len; i++) { | |||
jobject _strMethod = (*env)->GetObjectArrayElement(env, jobjArray, i); | |||
(*env)->SetObjectArrayElement(env, array, i, _strMethod); | |||
} | |||
return array; | |||
} | |||
jobject callVoidMethod(JNIEnv *env, jobject obj, jboolean staticValue, jmethodID methodID, jvalue *params) { | |||
if (staticValue) { | |||
(*env)->CallStaticVoidMethodA(env, obj, methodID, params); | |||
} else { | |||
(*env)->CallVoidMethodA(env, obj, methodID, params); | |||
} | |||
return (*env)->NewGlobalRef(env, NULL); | |||
} | |||
jobject callIntMethod(JNIEnv *env, jobject obj, jboolean staticValue, jmethodID methodID, jvalue *params) { | |||
jint intValue; | |||
if (staticValue) { | |||
intValue = (*env)->CallStaticIntMethodA(env, obj, methodID, params); | |||
} else { | |||
intValue = (*env)->CallIntMethodA(env, obj, methodID, params); | |||
} | |||
jclass clazz = (*env)->FindClass(env, "Ljava/lang/Integer;"); | |||
jmethodID methodIDInteger = (*env)->GetMethodID(env, clazz, "<init>", "(I)V"); | |||
return (*env)->NewObject(env, clazz, methodIDInteger, intValue); | |||
} | |||
jobject callObjectMethod(JNIEnv *env, jobject obj, jboolean staticValue, jmethodID methodID, jvalue *params) { | |||
if (staticValue) { | |||
return (*env)->CallStaticObjectMethodA(env, obj, methodID, params); | |||
} else { | |||
return (*env)->CallObjectMethodA(env, obj, methodID, params); | |||
} | |||
} | |||
JNIEXPORT jobject JNICALL Java_at_ssw_hotswap_test_access_jni_JNIMethodAccess_invokeMethodNative(JNIEnv *env, jclass c, jclass cls, jobject obj, jstring methodName, jstring retValue, jboolean staticValue, jstring descriptor, jobjectArray params) { | |||
const char *methodstr = (*env)->GetStringUTFChars(env, methodName, 0); | |||
const char *descriptorstr = (*env)->GetStringUTFChars(env, descriptor, 0); | |||
const char *retValuestr = (*env)->GetStringUTFChars(env, retValue, 0); | |||
jmethodID methodID; | |||
if (staticValue) { | |||
methodID = (*env)->GetStaticMethodID(env, cls, methodstr, descriptorstr); | |||
} else { | |||
methodID = (*env)->GetMethodID(env, cls, methodstr, descriptorstr); | |||
} | |||
jsize len = (*env)->GetArrayLength(env, params); | |||
jvalue *m = (jvalue*) malloc(sizeof (jvalue) * len); | |||
jvalue *mm = m; | |||
int i = 0; | |||
for (i; i < len; i++) { | |||
*mm = (jvalue)(*env)->GetObjectArrayElement(env, params, i); | |||
mm += 1; | |||
} | |||
jobject object = (*env)->NewGlobalRef(env, NULL); | |||
if (strcmp(retValuestr, "void") == 0) { | |||
object = callVoidMethod(env, obj, staticValue, methodID, m); | |||
} else if (strcmp(retValuestr, "int") == 0) { | |||
object = callIntMethod(env, obj, staticValue, methodID, m); | |||
} else if (strcmp(retValuestr, "java.lang.Object") == 0) { | |||
object = callObjectMethod(env, obj, staticValue, methodID, m); | |||
} else { | |||
jclass exc = (*env)->FindClass(env, "java.lang.NotImplementedException"); | |||
(*env)->ThrowNew(env, exc, "required retValue: bool/int/object"); | |||
} | |||
(*env)->ReleaseStringUTFChars(env, methodName, methodstr); | |||
(*env)->ReleaseStringUTFChars(env, descriptor, descriptorstr); | |||
(*env)->ReleaseStringUTFChars(env, retValue, retValuestr); | |||
return object; | |||
} | |||
@@ -0,0 +1,72 @@ | |||
/* | |||
* 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. | |||
* | |||
*/ | |||
#include <jni.h> | |||
#ifndef NATIVES | |||
#define NATIVES | |||
/* | |||
* Class: at_ssw_hotswap_test_natives_SimpleNativeTest_A | |||
* Method: value | |||
* Signature: ()I | |||
*/ | |||
JNIEXPORT jint JNICALL Java_at_ssw_hotswap_test_natives_SimpleNativeTest_00024A_value(JNIEnv *, jclass); | |||
/* | |||
* Class: at_ssw_hotswap_test_natives_SimpleNativeTest_A | |||
* Method: value2 | |||
* Signature: ()I | |||
*/ | |||
JNIEXPORT jint JNICALL Java_at_ssw_hotswap_test_natives_SimpleNativeTest_00024A_value2(JNIEnv *, jclass); | |||
/* | |||
* Class: at_ssw_hotswap_test_access_jni_JNIVMAccess | |||
* Method: findClass | |||
* Signature: (String)Class | |||
*/ | |||
JNIEXPORT jclass JNICALL Java_at_ssw_hotswap_test_access_jni_JNIVMAccess_findClassNative(JNIEnv *, jclass, jstring); | |||
/* | |||
* Class: at_ssw_hotswap_test_access_jni_JNIClassAccess | |||
* Method: findMethod | |||
* Signature: (Class, String)Object | |||
*/ | |||
JNIEXPORT jobject JNICALL Java_at_ssw_hotswap_test_access_jni_JNIClassAccess_findMethodNative(JNIEnv *, jclass, jclass, jstring); | |||
/* | |||
* Class: at_ssw_hotswap_test_access_jni_JNIClassAccess | |||
* Method: getMethods | |||
* Signature: (Class)Object[] | |||
*/ | |||
JNIEXPORT jobjectArray JNICALL Java_at_ssw_hotswap_test_access_jni_JNIClassAccess_getMethodsNative(JNIEnv *, jclass, jclass); | |||
/* | |||
* Class: at_ssw_hotswap_test_access_jni_JNIMethodAccess | |||
* Method: invokeMethod | |||
* Signature: (Class, String, Object)Value | |||
*/ | |||
JNIEXPORT jobject JNICALL Java_at_ssw_hotswap_test_access_jni_JNIMethodAccess_invokeMethod(JNIEnv *, jclass, jclass, jobject, jstring, jstring, jboolean, jstring); | |||
#endif |
@@ -0,0 +1 @@ | |||
include 'agent', 'framework', 'tests-java7', 'tests-java8', 'hotspot' |
@@ -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 { | |||
} |
@@ -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); | |||
} | |||
}); | |||
} | |||
} |
@@ -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()); | |||
} | |||
} |
@@ -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 { | |||
} |
@@ -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()); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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)); | |||
} | |||
} |
@@ -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)); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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()); | |||
} | |||
} |
@@ -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()); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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()); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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 { | |||
} |
@@ -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()); | |||
} | |||
} |
@@ -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()); | |||
} | |||
}); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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]); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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 { | |||
} |
@@ -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]); | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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()); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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 { | |||
} |
@@ -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()); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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()); | |||
} | |||
} |
@@ -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()); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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 "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("test", Helper.access(o)); | |||
__toVersion__(0); | |||
__toVersion__(1); | |||
__toVersion__(0); | |||
} | |||
} |
@@ -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 { | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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); | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} | |||
} | |||
} |