Browse Source

Extracting DCEVM patch & code into separate project

Making DCEVM to be toplevel project that clones HotSpot repository,
patches the code, builds JVM and tests it.
tags/light-jdk8u5+36
Ivan Dubrov 10 years ago
parent
commit
38ed95d3c0
69 changed files with 11618 additions and 0 deletions
  1. 5
    0
      .gitignore
  2. 4
    0
      agent/src/main/java/META-INF/MANIFEST.MF
  3. 18
    0
      agent/src/main/java/org/dcevm/agent/InstrumentationAgent.java
  4. 8
    0
      build.cmd
  5. 223
    0
      build.gradle
  6. 40
    0
      framework/src/main/java/org/dcevm/ClassRedefinitionPolicy.java
  7. 233
    0
      framework/src/main/java/org/dcevm/HotSwapTool.java
  8. 54
    0
      framework/src/main/java/org/dcevm/InstrumentationRedefiner.java
  9. 153
    0
      framework/src/main/java/org/dcevm/JDIRedefiner.java
  10. 37
    0
      framework/src/main/java/org/dcevm/Redefiner.java
  11. 101
    0
      framework/src/main/java/org/dcevm/TestClassAdapter.java
  12. 28
    0
      gradle.properties
  13. BIN
      gradle/wrapper/gradle-wrapper.jar
  14. 6
    0
      gradle/wrapper/gradle-wrapper.properties
  15. 164
    0
      gradlew
  16. 90
    0
      gradlew.bat
  17. 174
    0
      native/natives.c
  18. 72
    0
      native/natives.h
  19. 4251
    0
      patches/dcevm-jdk8u5-b13.patch
  20. 1
    0
      settings.gradle
  21. 49
    0
      tests-java7/src/test/java/org/dcevm/test/LightTestSuite.java
  22. 86
    0
      tests-java7/src/test/java/org/dcevm/test/TestUtil.java
  23. 98
    0
      tests-java7/src/test/java/org/dcevm/test/body/ArrayTest.java
  24. 53
    0
      tests-java7/src/test/java/org/dcevm/test/body/BodyTestSuite.java
  25. 68
    0
      tests-java7/src/test/java/org/dcevm/test/body/ClassRenamingTestCase.java
  26. 219
    0
      tests-java7/src/test/java/org/dcevm/test/body/EMCPTest.java
  27. 103
    0
      tests-java7/src/test/java/org/dcevm/test/body/FacTest.java
  28. 110
    0
      tests-java7/src/test/java/org/dcevm/test/body/FibTest.java
  29. 207
    0
      tests-java7/src/test/java/org/dcevm/test/body/MultipleThreadsTest.java
  30. 158
    0
      tests-java7/src/test/java/org/dcevm/test/body/OldActivationTest.java
  31. 96
    0
      tests-java7/src/test/java/org/dcevm/test/body/RedefinePrivateMethodTest.java
  32. 96
    0
      tests-java7/src/test/java/org/dcevm/test/body/RefactorActiveMethodTest.java
  33. 128
    0
      tests-java7/src/test/java/org/dcevm/test/body/SimpleStaticTest.java
  34. 300
    0
      tests-java7/src/test/java/org/dcevm/test/body/StaticTest.java
  35. 82
    0
      tests-java7/src/test/java/org/dcevm/test/body/StressTest.java
  36. 122
    0
      tests-java7/src/test/java/org/dcevm/test/eval/AddingInterfaceTest.java
  37. 42
    0
      tests-java7/src/test/java/org/dcevm/test/eval/EvalTestSuite.java
  38. 256
    0
      tests-java7/src/test/java/org/dcevm/test/eval/FractionTest.java
  39. 207
    0
      tests-java7/src/test/java/org/dcevm/test/eval/GeometryScenario.java
  40. 104
    0
      tests-java7/src/test/java/org/dcevm/test/fields/ComplexFieldTest.java
  41. 70
    0
      tests-java7/src/test/java/org/dcevm/test/fields/EnumTest.java
  42. 63
    0
      tests-java7/src/test/java/org/dcevm/test/fields/FieldAlignmentTest.java
  43. 184
    0
      tests-java7/src/test/java/org/dcevm/test/fields/FieldChangedOrderTest.java
  44. 278
    0
      tests-java7/src/test/java/org/dcevm/test/fields/FieldModificationTest.java
  45. 49
    0
      tests-java7/src/test/java/org/dcevm/test/fields/FieldsTestSuite.java
  46. 122
    0
      tests-java7/src/test/java/org/dcevm/test/fields/ObjectStressTest.java
  47. 97
    0
      tests-java7/src/test/java/org/dcevm/test/fields/RedefinePrivateFieldTest.java
  48. 78
    0
      tests-java7/src/test/java/org/dcevm/test/fields/StringFieldTest.java
  49. 123
    0
      tests-java7/src/test/java/org/dcevm/test/fields/YieldTest.java
  50. 166
    0
      tests-java7/src/test/java/org/dcevm/test/methods/AddMethodTest.java
  51. 121
    0
      tests-java7/src/test/java/org/dcevm/test/methods/AnnotationTest.java
  52. 92
    0
      tests-java7/src/test/java/org/dcevm/test/methods/ClassObjectHashcodeTest.java
  53. 79
    0
      tests-java7/src/test/java/org/dcevm/test/methods/ClassObjectSynchronizationTest.java
  54. 160
    0
      tests-java7/src/test/java/org/dcevm/test/methods/ClassReflectionTest.java
  55. 159
    0
      tests-java7/src/test/java/org/dcevm/test/methods/DeleteActiveMethodTest.java
  56. 152
    0
      tests-java7/src/test/java/org/dcevm/test/methods/MethodReflectionTest.java
  57. 49
    0
      tests-java7/src/test/java/org/dcevm/test/methods/MethodsTestSuite.java
  58. 247
    0
      tests-java7/src/test/java/org/dcevm/test/methods/OverrideMethodTest.java
  59. 88
    0
      tests-java7/src/test/java/org/dcevm/test/methods/SingleClassReflectionTest.java
  60. 123
    0
      tests-java7/src/test/java/org/dcevm/test/methods/SingleClassTest.java
  61. 67
    0
      tests-java7/src/test/java/org/dcevm/test/structural/AnonymousClassInMethodTest.java
  62. 144
    0
      tests-java7/src/test/java/org/dcevm/test/structural/InterfaceTest.java
  63. 71
    0
      tests-java7/src/test/java/org/dcevm/test/structural/RedefineClassClassTest.java
  64. 149
    0
      tests-java7/src/test/java/org/dcevm/test/structural/RedefineObjectClassTest.java
  65. 45
    0
      tests-java7/src/test/java/org/dcevm/test/structural/StructuralTestSuite.java
  66. 124
    0
      tests-java7/src/test/java/org/dcevm/test/structural/ThisTypeChange.java
  67. 81
    0
      tests-java7/src/test/java/org/dcevm/test/util/HotSwapTestHelper.java
  68. 110
    0
      tests-java8/src/test/java/org/dcevm/test/methods/DefaultMethodsTest.java
  69. 81
    0
      tests-java8/src/test/java/org/dcevm/test/util/HotSwapTestHelper.java

+ 5
- 0
.gitignore View File

@@ -0,0 +1,5 @@
/.gradle
/.idea
/hotspot
build
*.iml

+ 4
- 0
agent/src/main/java/META-INF/MANIFEST.MF View File

@@ -0,0 +1,4 @@
Manifest-Version: 1.0
Can-Redefine-Classes: true
Agent-Class: org.dcevm.agent.InstrumentationAgent
Premain-Class: org.dcevm.agent.InstrumentationAgent

+ 18
- 0
agent/src/main/java/org/dcevm/agent/InstrumentationAgent.java View File

@@ -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;
}
}

+ 8
- 0
build.cmd View File

@@ -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" %*'

+ 223
- 0
build.gradle View File

@@ -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'
}
}

+ 40
- 0
framework/src/main/java/org/dcevm/ClassRedefinitionPolicy.java View File

@@ -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;
}

+ 233
- 0
framework/src/main/java/org/dcevm/HotSwapTool.java View File

@@ -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;
}
}

+ 54
- 0
framework/src/main/java/org/dcevm/InstrumentationRedefiner.java View File

@@ -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.
}
}

+ 153
- 0
framework/src/main/java/org/dcevm/JDIRedefiner.java View File

@@ -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 + "'" );
}
}

+ 37
- 0
framework/src/main/java/org/dcevm/Redefiner.java View File

@@ -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;
}

+ 101
- 0
framework/src/main/java/org/dcevm/TestClassAdapter.java View File

@@ -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;
}
}


+ 28
- 0
gradle.properties View File

@@ -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

BIN
gradle/wrapper/gradle-wrapper.jar View File


+ 6
- 0
gradle/wrapper/gradle-wrapper.properties View File

@@ -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

+ 164
- 0
gradlew View File

@@ -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 "$@"

+ 90
- 0
gradlew.bat View File

@@ -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

+ 174
- 0
native/natives.c View File

@@ -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;
}


+ 72
- 0
native/natives.h View File

@@ -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

+ 4251
- 0
patches/dcevm-jdk8u5-b13.patch
File diff suppressed because it is too large
View File


+ 1
- 0
settings.gradle View File

@@ -0,0 +1 @@
include 'agent', 'framework', 'tests-java7', 'tests-java8', 'hotspot'

+ 49
- 0
tests-java7/src/test/java/org/dcevm/test/LightTestSuite.java View File

@@ -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 {
}

+ 86
- 0
tests-java7/src/test/java/org/dcevm/test/TestUtil.java View File

@@ -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);
}
});
}

}

+ 98
- 0
tests-java7/src/test/java/org/dcevm/test/body/ArrayTest.java View File

@@ -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());
}
}

+ 53
- 0
tests-java7/src/test/java/org/dcevm/test/body/BodyTestSuite.java View File

@@ -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 {
}

+ 68
- 0
tests-java7/src/test/java/org/dcevm/test/body/ClassRenamingTestCase.java View File

@@ -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());
}
}

+ 219
- 0
tests-java7/src/test/java/org/dcevm/test/body/EMCPTest.java View File

@@ -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);
}
}

+ 103
- 0
tests-java7/src/test/java/org/dcevm/test/body/FacTest.java View File

@@ -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));
}
}

+ 110
- 0
tests-java7/src/test/java/org/dcevm/test/body/FibTest.java View File

@@ -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));
}
}

+ 207
- 0
tests-java7/src/test/java/org/dcevm/test/body/MultipleThreadsTest.java View File

@@ -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);


}
}

+ 158
- 0
tests-java7/src/test/java/org/dcevm/test/body/OldActivationTest.java View File

@@ -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;
}
}

+ 96
- 0
tests-java7/src/test/java/org/dcevm/test/body/RedefinePrivateMethodTest.java View File

@@ -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);
}
}

+ 96
- 0
tests-java7/src/test/java/org/dcevm/test/body/RefactorActiveMethodTest.java View File

@@ -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());
}
}

+ 128
- 0
tests-java7/src/test/java/org/dcevm/test/body/SimpleStaticTest.java View File

@@ -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());
}
}

+ 300
- 0
tests-java7/src/test/java/org/dcevm/test/body/StaticTest.java View File

@@ -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);

}


}

+ 82
- 0
tests-java7/src/test/java/org/dcevm/test/body/StressTest.java View File

@@ -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());
}
}

+ 122
- 0
tests-java7/src/test/java/org/dcevm/test/eval/AddingInterfaceTest.java View File

@@ -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;
}
}

+ 42
- 0
tests-java7/src/test/java/org/dcevm/test/eval/EvalTestSuite.java View File

@@ -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 {
}

+ 256
- 0
tests-java7/src/test/java/org/dcevm/test/eval/FractionTest.java View File

@@ -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());
}
}

+ 207
- 0
tests-java7/src/test/java/org/dcevm/test/eval/GeometryScenario.java View File

@@ -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());
}
});
}
}

+ 104
- 0
tests-java7/src/test/java/org/dcevm/test/fields/ComplexFieldTest.java View File

@@ -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);
}
}

+ 70
- 0
tests-java7/src/test/java/org/dcevm/test/fields/EnumTest.java View File

@@ -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]);
}
}

+ 63
- 0
tests-java7/src/test/java/org/dcevm/test/fields/FieldAlignmentTest.java View File

@@ -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);
}
}

+ 184
- 0
tests-java7/src/test/java/org/dcevm/test/fields/FieldChangedOrderTest.java View File

@@ -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);
}
}

+ 278
- 0
tests-java7/src/test/java/org/dcevm/test/fields/FieldModificationTest.java View File

@@ -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);
}
}

+ 49
- 0
tests-java7/src/test/java/org/dcevm/test/fields/FieldsTestSuite.java View File

@@ -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 {
}

+ 122
- 0
tests-java7/src/test/java/org/dcevm/test/fields/ObjectStressTest.java View File

@@ -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]);
}
}
}

+ 97
- 0
tests-java7/src/test/java/org/dcevm/test/fields/RedefinePrivateFieldTest.java View File

@@ -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);
}
}

+ 78
- 0
tests-java7/src/test/java/org/dcevm/test/fields/StringFieldTest.java View File

@@ -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);
}
}

+ 123
- 0
tests-java7/src/test/java/org/dcevm/test/fields/YieldTest.java View File

@@ -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;
}
}

+ 166
- 0
tests-java7/src/test/java/org/dcevm/test/methods/AddMethodTest.java View File

@@ -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;
}
}

+ 121
- 0
tests-java7/src/test/java/org/dcevm/test/methods/AnnotationTest.java View File

@@ -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);
}

}

+ 92
- 0
tests-java7/src/test/java/org/dcevm/test/methods/ClassObjectHashcodeTest.java View File

@@ -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());
}
}

+ 79
- 0
tests-java7/src/test/java/org/dcevm/test/methods/ClassObjectSynchronizationTest.java View File

@@ -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);
}
}

+ 160
- 0
tests-java7/src/test/java/org/dcevm/test/methods/ClassReflectionTest.java View File

@@ -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);
}
}

+ 159
- 0
tests-java7/src/test/java/org/dcevm/test/methods/DeleteActiveMethodTest.java View File

@@ -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;
}
}

+ 152
- 0
tests-java7/src/test/java/org/dcevm/test/methods/MethodReflectionTest.java View File

@@ -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);
}
}

+ 49
- 0
tests-java7/src/test/java/org/dcevm/test/methods/MethodsTestSuite.java View File

@@ -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 {
}

+ 247
- 0
tests-java7/src/test/java/org/dcevm/test/methods/OverrideMethodTest.java View File

@@ -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());
}
}

+ 88
- 0
tests-java7/src/test/java/org/dcevm/test/methods/SingleClassReflectionTest.java View File

@@ -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);
}

}

+ 123
- 0
tests-java7/src/test/java/org/dcevm/test/methods/SingleClassTest.java View File

@@ -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);
}
}

+ 67
- 0
tests-java7/src/test/java/org/dcevm/test/structural/AnonymousClassInMethodTest.java View File

@@ -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());
}
}

+ 144
- 0
tests-java7/src/test/java/org/dcevm/test/structural/InterfaceTest.java View File

@@ -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());
}
}

+ 71
- 0
tests-java7/src/test/java/org/dcevm/test/structural/RedefineClassClassTest.java View File

@@ -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);


}
}

+ 149
- 0
tests-java7/src/test/java/org/dcevm/test/structural/RedefineObjectClassTest.java View File

@@ -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);
}
}

+ 45
- 0
tests-java7/src/test/java/org/dcevm/test/structural/StructuralTestSuite.java View File

@@ -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 {
}

+ 124
- 0
tests-java7/src/test/java/org/dcevm/test/structural/ThisTypeChange.java View File

@@ -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;
}
}

+ 81
- 0
tests-java7/src/test/java/org/dcevm/test/util/HotSwapTestHelper.java View File

@@ -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);
}
}
}

+ 110
- 0
tests-java8/src/test/java/org/dcevm/test/methods/DefaultMethodsTest.java View File

@@ -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);
}
}

+ 81
- 0
tests-java8/src/test/java/org/dcevm/test/util/HotSwapTestHelper.java View File

@@ -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);
}
}
}

Loading…
Cancel
Save