diff --git a/src/macosx/native/sun/awt/CDataTransferer.m b/src/macosx/native/sun/awt/CDataTransferer.m index 5e997bf7ab90e339e0c0d757a66d630fb39381f4..09a7e5c3a4cbe357b988e951b978f196302d3a2a 100644 --- a/src/macosx/native/sun/awt/CDataTransferer.m +++ b/src/macosx/native/sun/awt/CDataTransferer.m @@ -28,6 +28,7 @@ #import #import +#import "jni_util.h" #include "ThreadUtilities.h" @@ -172,7 +173,9 @@ JNF_COCOA_ENTER(env); NSData *tiffImage = [imageRep TIFFRepresentation]; jsize tiffSize = (jsize)[tiffImage length]; // #warning 64-bit: -length returns NSUInteger, but NewByteArray takes jsize returnValue = (*env)->NewByteArray(env, tiffSize); + CHECK_NULL_RETURN(returnValue, nil); jbyte *tiffData = (jbyte *)(*env)->GetPrimitiveArrayCritical(env, returnValue, 0); + CHECK_NULL_RETURN(tiffData, nil); [tiffImage getBytes:tiffData]; (*env)->ReleasePrimitiveArrayCritical(env, returnValue, tiffData, 0); // Do not use JNI_COMMIT, as that will not free the buffer copy when +ProtectJavaHeap is on. [imageRep release]; @@ -184,12 +187,13 @@ JNF_COCOA_EXIT(env); static jobject getImageForByteStream(JNIEnv *env, jbyteArray sourceData) { - if (sourceData == NULL) return NULL; + CHECK_NULL_RETURN(sourceData, NULL); jsize sourceSize = (*env)->GetArrayLength(env, sourceData); if (sourceSize == 0) return NULL; jbyte *sourceBytes = (*env)->GetPrimitiveArrayCritical(env, sourceData, NULL); + CHECK_NULL_RETURN(sourceBytes, NULL); NSData *rawData = [NSData dataWithBytes:sourceBytes length:sourceSize]; NSImage *newImage = [[NSImage alloc] initWithData:rawData]; @@ -197,8 +201,7 @@ static jobject getImageForByteStream(JNIEnv *env, jbyteArray sourceData) [newImage release]; (*env)->ReleasePrimitiveArrayCritical(env, sourceData, sourceBytes, JNI_ABORT); - - if (newImage == nil) return NULL; + CHECK_NULL_RETURN(newImage, NULL); // The ownership of the NSImage is passed to the new CImage jobject. No need to release it. static JNF_CLASS_CACHE(jc_CImage, "sun/lwawt/macosx/CImage"); @@ -231,7 +234,8 @@ static jobjectArray CreateJavaFilenameArray(JNIEnv *env, NSArray *filenameArray) if (filenameCount == 0) return nil; // Get the java.lang.String class object: - jclass stringClazz = (*env)->FindClass(env, "java/lang/String"); // can't be null + jclass stringClazz = (*env)->FindClass(env, "java/lang/String"); + CHECK_NULL_RETURN(stringClazz, nil); jobject jfilenameArray = (*env)->NewObjectArray(env, filenameCount, stringClazz, NULL); // AWT_THREADING Safe (known object) if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionDescribe(env); diff --git a/src/macosx/native/sun/awt/LWCToolkit.m b/src/macosx/native/sun/awt/LWCToolkit.m index 3300e2ddc213b6ca68d8192c04ef926af6244355..5e2dd6cb43df9f881745a4ed00c1334e14bb4c4f 100644 --- a/src/macosx/native/sun/awt/LWCToolkit.m +++ b/src/macosx/native/sun/awt/LWCToolkit.m @@ -200,13 +200,17 @@ Java_sun_lwawt_macosx_LWCToolkit_initIDs gNumberOfButtons = sun_lwawt_macosx_LWCToolkit_BUTTONS; jclass inputEventClazz = (*env)->FindClass(env, "java/awt/event/InputEvent"); + CHECK_NULL(inputEventClazz); jmethodID getButtonDownMasksID = (*env)->GetStaticMethodID(env, inputEventClazz, "getButtonDownMasks", "()[I"); + CHECK_NULL(getButtonDownMasksID); jintArray obj = (jintArray)(*env)->CallStaticObjectMethod(env, inputEventClazz, getButtonDownMasksID); jint * tmp = (*env)->GetIntArrayElements(env, obj, JNI_FALSE); + CHECK_NULL(tmp); gButtonDownMasks = (jint*)SAFE_SIZE_ARRAY_ALLOC(malloc, sizeof(jint), gNumberOfButtons); if (gButtonDownMasks == NULL) { gNumberOfButtons = 0; + (*env)->ReleaseIntArrayElements(env, obj, tmp, JNI_ABORT); JNU_ThrowOutOfMemoryError(env, NULL); return; } @@ -240,7 +244,7 @@ static UInt32 RGB(NSColor *c) { return ((ia & 0xFF) << 24) | ((ir & 0xFF) << 16) | ((ig & 0xFF) << 8) | ((ib & 0xFF) << 0); } -void doLoadNativeColors(JNIEnv *env, jintArray jColors, BOOL useAppleColors) { +BOOL doLoadNativeColors(JNIEnv *env, jintArray jColors, BOOL useAppleColors) { jint len = (*env)->GetArrayLength(env, jColors); UInt32 colorsArray[len]; @@ -254,8 +258,12 @@ void doLoadNativeColors(JNIEnv *env, jintArray jColors, BOOL useAppleColors) { }]; jint *_colors = (*env)->GetPrimitiveArrayCritical(env, jColors, 0); + if (_colors == NULL) { + return NO; + } memcpy(_colors, colors, len * sizeof(UInt32)); (*env)->ReleasePrimitiveArrayCritical(env, jColors, _colors, 0); + return YES; } /** @@ -267,8 +275,9 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_loadNativeColors (JNIEnv *env, jobject peer, jintArray jSystemColors, jintArray jAppleColors) { JNF_COCOA_ENTER(env); - doLoadNativeColors(env, jSystemColors, NO); - doLoadNativeColors(env, jAppleColors, YES); + if (doLoadNativeColors(env, jSystemColors, NO)) { + doLoadNativeColors(env, jAppleColors, YES); + } JNF_COCOA_EXIT(env); } diff --git a/src/share/instrument/Reentrancy.c b/src/share/instrument/Reentrancy.c index 58cbfdd1b53ec2c90a226f102375dda88066ba31..0b526c10a4543e99490cb462b3cbc6b128d6d522 100644 --- a/src/share/instrument/Reentrancy.c +++ b/src/share/instrument/Reentrancy.c @@ -130,6 +130,7 @@ tryToAcquireReentrancyToken( jvmtiEnv * jvmtienv, error = confirmingTLSSet ( jvmtienv, thread, JPLIS_CURRENTLY_INSIDE_TOKEN); + check_phase_ret_false(error); jplis_assert(error == JVMTI_ERROR_NONE); if ( error != JVMTI_ERROR_NONE ) { result = JNI_FALSE; @@ -158,6 +159,7 @@ releaseReentrancyToken( jvmtiEnv * jvmtienv, error = confirmingTLSSet( jvmtienv, thread, JPLIS_CURRENTLY_OUTSIDE_TOKEN); + check_phase_ret(error); jplis_assert(error == JVMTI_ERROR_NONE); } diff --git a/src/share/native/com/sun/java/util/jar/pack/coding.cpp b/src/share/native/com/sun/java/util/jar/pack/coding.cpp index 6cedfd80de1d4ae785bb49058427776df7eb1ec0..66ecc1bff63d3cdba14d3bbdccfa2f2e2392a882 100644 --- a/src/share/native/com/sun/java/util/jar/pack/coding.cpp +++ b/src/share/native/com/sun/java/util/jar/pack/coding.cpp @@ -32,6 +32,8 @@ #include #include +#include "jni_util.h" + #include "defines.h" #include "bytes.h" #include "utils.h" @@ -147,7 +149,7 @@ coding* coding::findBySpec(int spec) { break; } coding* ptr = NEW(coding, 1); - CHECK_NULL_0(ptr); + CHECK_NULL_RETURN(ptr, 0); coding* c = ptr->initFrom(spec); if (c == null) { mtrace('f', ptr, 0); diff --git a/src/share/native/com/sun/java/util/jar/pack/defines.h b/src/share/native/com/sun/java/util/jar/pack/defines.h index b202892fa7e7920e9d52c507a7a49da846fd4dbf..644b9ca9af636d570fefaaef1848682f0e2c3e07 100644 --- a/src/share/native/com/sun/java/util/jar/pack/defines.h +++ b/src/share/native/com/sun/java/util/jar/pack/defines.h @@ -158,10 +158,6 @@ enum { false, true }; #define CHECK_(y) _CHECK_DO(aborting(), return y) #define CHECK_0 _CHECK_DO(aborting(), return 0) -#define CHECK_NULL(p) _CHECK_DO((p)==null, return) -#define CHECK_NULL_(y,p) _CHECK_DO((p)==null, return y) -#define CHECK_NULL_0(p) _CHECK_DO((p)==null, return 0) - #define CHECK_COUNT(t) if (t < 0){abort("bad value count");} CHECK #define STR_TRUE "true" diff --git a/test/java/lang/instrument/DaemonThread/DummyAgent.java b/test/java/lang/instrument/DaemonThread/DummyAgent.java new file mode 100644 index 0000000000000000000000000000000000000000..64b4d59cf1808ad4daa321d8cac7a82d47d9e762 --- /dev/null +++ b/test/java/lang/instrument/DaemonThread/DummyAgent.java @@ -0,0 +1,46 @@ +/* + * Copyright 2014 Goldman Sachs. + * Copyright (c) 2014, 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. + */ + +import java.lang.instrument.ClassFileTransformer; +import java.lang.instrument.IllegalClassFormatException; +import java.lang.instrument.Instrumentation; +import java.security.ProtectionDomain; + +public class DummyAgent implements ClassFileTransformer { + @Override + public byte[] transform(ClassLoader loader, String className, + Class classBeingRedefined, ProtectionDomain protectionDomain, + byte[] classfileBuffer) throws IllegalClassFormatException { + + /* The Daemon Thread bug is timing dependent and you want the transform method + * to return ASAP - so just return the buffer will be fine + */ + return classfileBuffer; + } + + public static void premain(String agentArgs, Instrumentation inst) { + inst.addTransformer(new DummyAgent(), false); + } + +} diff --git a/test/java/lang/instrument/DaemonThread/DummyClass.java b/test/java/lang/instrument/DaemonThread/DummyClass.java new file mode 100644 index 0000000000000000000000000000000000000000..18d671afc096f146a7281f2162d80c0d4995ff40 --- /dev/null +++ b/test/java/lang/instrument/DaemonThread/DummyClass.java @@ -0,0 +1,27 @@ +/* + * Copyright 2014 Goldman Sachs. + * Copyright (c) 2014, 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. + */ + +/* Just a dummy class for loading */ +public class DummyClass { +} diff --git a/test/java/lang/instrument/DaemonThread/TestDaemonThread.java b/test/java/lang/instrument/DaemonThread/TestDaemonThread.java new file mode 100644 index 0000000000000000000000000000000000000000..20c9077d02fdc9ba28c2cb5068fa04ae70d54d51 --- /dev/null +++ b/test/java/lang/instrument/DaemonThread/TestDaemonThread.java @@ -0,0 +1,72 @@ +/* + * Copyright 2014 Goldman Sachs. + * Copyright (c) 2014, 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. + */ +/* @test + * @bug 7142035 + * @summary Assert in java.lang.instrument agents during shutdown when classloading occurs after shutdown + * @library /lib/testlibrary + * + * @build DummyAgent DummyClass TestDaemonThreadLauncher TestDaemonThread + * @run shell ../MakeJAR3.sh DummyAgent + * @run main TestDaemonThreadLauncher /timeout=240 + * + */ +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +public class TestDaemonThread implements Runnable{ + File classpath; + + public TestDaemonThread(File classpath) { + this.classpath = classpath; + } + + @Override + public void run() { + + + try { + URL u = this.getClass().getClassLoader().getResource("DummyClass.class"); + String path = u.getPath(); + String parent = u.getPath().substring(0, path.lastIndexOf('/')+1); + URL parentURL = new URL(u, parent); + System.out.println(parentURL); + /* Load lots of class by creating multiple classloaders */ + for(;;) { + ClassLoader cl = new URLClassLoader(new URL[] {parentURL}, null); + cl.loadClass("DummyClass"); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static void main(String[] args) throws Exception { + Thread t = new Thread(new TestDaemonThread(new File(args[0]))); + /* The important part of the bug is that a Daemon thread can continue to load classes after shutdown */ + t.setDaemon(true); + t.start(); + Thread.sleep(200); + } +} diff --git a/test/java/lang/instrument/DaemonThread/TestDaemonThreadLauncher.java b/test/java/lang/instrument/DaemonThread/TestDaemonThreadLauncher.java new file mode 100644 index 0000000000000000000000000000000000000000..9660bbfa9dcf9ed5643932a56b8f0703b0f3b215 --- /dev/null +++ b/test/java/lang/instrument/DaemonThread/TestDaemonThreadLauncher.java @@ -0,0 +1,44 @@ +/* + * Copyright 2014 Goldman Sachs. + * Copyright (c) 2014, 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. + */ + + +import jdk.testlibrary.JDKToolLauncher; +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; + +import java.io.IOException; +import java.nio.file.Path; + +public class TestDaemonThreadLauncher { + + private static ProcessBuilder processBuilder = new ProcessBuilder(); + + public static void main(String args[]) throws Exception { + for(int i=0; i<50; i++) { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-javaagent:DummyAgent.jar", "TestDaemonThread", "."); + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + analyzer.shouldNotContain("ASSERTION FAILED"); + } + } +}