We were letting the jit and the main thread race on class definition.
If the 'leader' changes then we would end up with the test class
having an unexpected definition, causing the test to fail. We fixed
this by making sure all threads get the same definition regardless of
speed.
Bug:
34799243
Test: mma -j40 test-art-host
Test: stress --cpu 60 &; \
while ./test/run-test --host --jit --gcstress --64 934 ; do ; done
Test: stress --cpu 60 &; \
while ./test/run-test --host --jit --gcstress --64 935 ; do ; done
Test: stress --cpu 60 &; \
while ./test/run-test --host --jit --gcstress --64 938 ; do ; done
Change-Id: I0d6785b4c3c41db1d655cf1ff22be60809923a7a
}
public static void main(String[] args) {
+ // Don't pop transformations. Make sure that even if 2 threads race to define the class both
+ // will get the same result.
+ setPopRetransformations(false);
addCommonTransformationResult("Transform", CLASS_BYTES, DEX_BYTES);
enableCommonRetransformation(true);
try {
}
}
+ private static native void setPopRetransformations(boolean should_pop);
// Transforms the class
private static native void enableCommonRetransformation(boolean enable);
private static native void addCommonTransformationResult(String target_name,
import java.lang.reflect.Method;
public class TestMain {
- public static void runTest() {
+ public static void runTest() throws Exception {
Transform t = new Transform();
- try {
- // Call functions with reflection. Since the sayGoodbye function does not exist in the
- // LTransform; when we compile this for the first time we need to use reflection.
- Method hi = Transform.class.getMethod("sayHi");
- Method bye = Transform.class.getMethod("sayGoodbye");
- hi.invoke(t);
- t.sayHi();
- bye.invoke(t);
- } catch (Exception e) {
- System.out.println("Unexpected error occured! " + e.toString());
- e.printStackTrace();
- }
+ // Call functions with reflection. Since the sayGoodbye function does not exist in the
+ // LTransform; when we compile this for the first time we need to use reflection.
+ Method hi = Transform.class.getMethod("sayHi");
+ Method bye = Transform.class.getMethod("sayGoodbye");
+ hi.invoke(t);
+ t.sayHi();
+ bye.invoke(t);
}
}
}
public static void main(String[] args) {
+ setPopRetransformations(false);
addCommonTransformationResult("Transform", CLASS_BYTES, DEX_BYTES);
enableCommonRetransformation(true);
try {
Method run_test = klass.getMethod("runTest");
run_test.invoke(null);
+ // Remove the original transformation. It has been used by now.
+ popTransformationFor("Transform");
// Make sure we don't get called for transformation again.
addCommonTransformationResult("Transform", new byte[0], new byte[0]);
doCommonClassRetransformation(new_loader.loadClass("Transform"));
private static native void addCommonTransformationResult(String target_name,
byte[] class_bytes,
byte[] dex_bytes);
+ private static native void setPopRetransformations(boolean should_pop);
+ private static native void popTransformationFor(String target_name);
}
}
public static void main(String[] args) {
- // TODO WHAT TO TRANSFORM
+ setPopRetransformations(false);
addCommonTransformationResult("java/util/OptionalLong", CLASS_BYTES, DEX_BYTES);
enableCommonRetransformation(true);
try {
}
}
+ private static native void setPopRetransformations(boolean should_pop);
// Transforms the class
private static native void enableCommonRetransformation(boolean enable);
private static native void addCommonTransformationResult(String target_name,
// Map from class name to transformation result.
std::map<std::string, std::deque<CommonTransformationResult>> gTransformations;
+bool gPopTransformations = true;
extern "C" JNIEXPORT void JNICALL Java_Main_addCommonTransformationResult(JNIEnv* env,
jclass,
memcpy(new_data, desired_array.data(), desired_array.size());
*new_class_data = new_data;
*new_class_data_len = desired_array.size();
+ if (gPopTransformations) {
+ gTransformations[name_str].pop_front();
+ }
+ }
+}
+
+extern "C" JNIEXPORT void Java_Main_setPopRetransformations(JNIEnv*,
+ jclass,
+ jboolean enable) {
+ gPopTransformations = enable;
+}
+
+extern "C" JNIEXPORT void Java_Main_popTransformationFor(JNIEnv* env,
+ jclass,
+ jstring class_name) {
+ const char* name_chrs = env->GetStringUTFChars(class_name, nullptr);
+ std::string name_str(name_chrs);
+ env->ReleaseStringUTFChars(class_name, name_chrs);
+ if (gTransformations.find(name_str) != gTransformations.end() &&
+ gTransformations[name_str].size() > 0) {
gTransformations[name_str].pop_front();
+ } else {
+ std::stringstream err;
+ err << "No transformations found for class " << name_str;
+ std::string message = err.str();
+ env->ThrowNew(env->FindClass("java/lang/Exception"), message.c_str());
}
}