# HG changeset patch # User amurillo # Date 1441922120 25200 # Node ID 7ecf45f5fa4651ecd4db9f1661ad8265eb5be264 # Parent 4b948e5a3e77e9d39dd6cb140f9a4e9e6fe3470e# Parent 040b1184f05f44ffdd9068b1bda2e75cba82cb1d Merge diff -r 4b948e5a3e77 -r 7ecf45f5fa46 make/lib/CoreLibraries.gmk --- a/make/lib/CoreLibraries.gmk Thu Sep 10 17:56:24 2015 +0200 +++ b/make/lib/CoreLibraries.gmk Thu Sep 10 14:55:20 2015 -0700 @@ -239,6 +239,48 @@ ########################################################################################## +$(eval $(call SetupNativeCompilation,BUILD_LIBJIMAGE, \ + LIBRARY := jimage, \ + OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ + OPTIMIZATION := LOW, \ + SRC := $(JDK_TOPDIR)/src/java.base/share/native/libjimage \ + $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjimage, \ + EXCLUDES := $(LIBJIMAGE_EXCLUDES), \ + CFLAGS := $(CFLAGS_JDKLIB) \ + $(JIMAGELIB_CPPFLAGS) \ + -I$(JDK_TOPDIR)/src/java.base/share/native/libjava \ + -I$(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjava \ + -I$(JDK_TOPDIR)/src/java.base/share/native/libjimage \ + -I$(SUPPORT_OUTPUTDIR)/headers/java.base, \ + CFLAGS_unix := -UDEBUG, \ + MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjimage/mapfile-vers, \ + LDFLAGS := $(LDFLAGS_JDKLIB) \ + $(call SET_SHARED_LIBRARY_ORIGIN) \ + $(EXPORT_JIMAGE_FUNCS), \ + LDFLAGS_windows := -export:JIMAGE_Open -export:JIMAGE_Close \ + -export:JIMAGE_PackageToModule \ + -export:JIMAGE_FindResource -export:JIMAGE_GetResource \ + -export:JIMAGE_ResourceIterator, \ + LDFLAGS_SUFFIX_unix := -ljvm -ldl $(LIBCXX), \ + LDFLAGS_SUFFIX_linux := , \ + LDFLAGS_SUFFIX_solaris := -lc, \ + LDFLAGS_SUFFIX_aix := ,\ + LDFLAGS_SUFFIX_macosx := -lc++, \ + LDFLAGS_SUFFIX_windows := jvm.lib, \ + VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \ + RC_FLAGS := $(RC_FLAGS) \ + -D "JDK_FNAME=jimage.dll" \ + -D "JDK_INTERNAL_NAME=jimage" \ + -D "JDK_FTYPE=0x2L", \ + OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjimage, \ + DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES))) + +$(BUILD_LIBJIMAGE): $(BUILD_LIBJAVA) + +TARGETS += $(BUILD_LIBJIMAGE) + +########################################################################################## + LIBJLI_SRC_DIRS := $(call FindSrcDirsForLib, java.base, jli) LIBJLI_CFLAGS := $(CFLAGS_JDKLIB) diff -r 4b948e5a3e77 -r 7ecf45f5fa46 make/mapfiles/libjava/mapfile-vers --- a/make/mapfiles/libjava/mapfile-vers Thu Sep 10 17:56:24 2015 +0200 +++ b/make/mapfiles/libjava/mapfile-vers Thu Sep 10 14:55:20 2015 -0700 @@ -240,16 +240,6 @@ Java_java_util_TimeZone_getSystemTimeZoneID; Java_java_util_TimeZone_getSystemGMTOffsetID; Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8; - Java_jdk_internal_jimage_ImageNativeSubstrate_openImage; - Java_jdk_internal_jimage_ImageNativeSubstrate_closeImage; - Java_jdk_internal_jimage_ImageNativeSubstrate_getIndexAddress; - Java_jdk_internal_jimage_ImageNativeSubstrate_getDataAddress; - Java_jdk_internal_jimage_ImageNativeSubstrate_read; - Java_jdk_internal_jimage_ImageNativeSubstrate_readCompressed; - Java_jdk_internal_jimage_ImageNativeSubstrate_getStringBytes; - Java_jdk_internal_jimage_ImageNativeSubstrate_getAttributes; - Java_jdk_internal_jimage_ImageNativeSubstrate_findAttributes; - Java_jdk_internal_jimage_ImageNativeSubstrate_attributeOffsets; Java_sun_misc_MessageUtils_toStderr; Java_sun_misc_MessageUtils_toStdout; Java_sun_misc_NativeSignalHandler_handle0; diff -r 4b948e5a3e77 -r 7ecf45f5fa46 make/mapfiles/libjimage/mapfile-vers --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/mapfiles/libjimage/mapfile-vers Thu Sep 10 14:55:20 2015 -0700 @@ -0,0 +1,55 @@ +# +# Copyright (c) 2015, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# + +# Define public interface. + +SUNWprivate_1.1 { + global: + JNI_OnLoad; + Java_jdk_internal_jimage_ImageNativeSubstrate_openImage; + Java_jdk_internal_jimage_ImageNativeSubstrate_closeImage; + Java_jdk_internal_jimage_ImageNativeSubstrate_getIndexAddress; + Java_jdk_internal_jimage_ImageNativeSubstrate_getDataAddress; + Java_jdk_internal_jimage_ImageNativeSubstrate_read; + Java_jdk_internal_jimage_ImageNativeSubstrate_readCompressed; + Java_jdk_internal_jimage_ImageNativeSubstrate_getStringBytes; + Java_jdk_internal_jimage_ImageNativeSubstrate_getAttributes; + Java_jdk_internal_jimage_ImageNativeSubstrate_findAttributes; + Java_jdk_internal_jimage_ImageNativeSubstrate_attributeOffsets; + Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Open; + Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Close; + Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1FindResource; + Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1GetResource; + Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1PackageToModule; + Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Resources; + JIMAGE_Open; + JIMAGE_Close; + JIMAGE_PackageToModule; + JIMAGE_FindResource; + JIMAGE_GetResource; + JIMAGE_ResourceIterator; + local: + *; +}; diff -r 4b948e5a3e77 -r 7ecf45f5fa46 make/mapfiles/libzip/reorder-sparc --- a/make/mapfiles/libzip/reorder-sparc Thu Sep 10 17:56:24 2015 +0200 +++ b/make/mapfiles/libzip/reorder-sparc Thu Sep 10 14:55:20 2015 -0700 @@ -12,6 +12,7 @@ text: .text%addMetaName: OUTPUTDIR/zip_util.o; text: .text%ZIP_FindEntry; text: .text%ZIP_GetEntry; +text: .text%ZIP_InflateFully; text: .text%ZIP_Lock; text: .text%ZIP_Unlock; text: .text%ZIP_FreeEntry; diff -r 4b948e5a3e77 -r 7ecf45f5fa46 make/mapfiles/libzip/reorder-sparcv9 --- a/make/mapfiles/libzip/reorder-sparcv9 Thu Sep 10 17:56:24 2015 +0200 +++ b/make/mapfiles/libzip/reorder-sparcv9 Thu Sep 10 14:55:20 2015 -0700 @@ -11,6 +11,7 @@ text: .text%addMetaName: OUTPUTDIR/zip_util.o; text: .text%ZIP_FindEntry; text: .text%ZIP_GetEntry; +text: .text%ZIP_InflateFully; text: .text%ZIP_Lock; text: .text%ZIP_Unlock; text: .text%ZIP_FreeEntry; diff -r 4b948e5a3e77 -r 7ecf45f5fa46 make/mapfiles/libzip/reorder-x86 --- a/make/mapfiles/libzip/reorder-x86 Thu Sep 10 17:56:24 2015 +0200 +++ b/make/mapfiles/libzip/reorder-x86 Thu Sep 10 14:55:20 2015 -0700 @@ -12,6 +12,7 @@ text: .text%addMetaName: OUTPUTDIR/zip_util.o; text: .text%ZIP_FindEntry; text: .text%ZIP_GetEntry; +text: .text%ZIP_InflateFully; text: .text%ZIP_Lock; text: .text%ZIP_Unlock; text: .text%ZIP_FreeEntry; diff -r 4b948e5a3e77 -r 7ecf45f5fa46 make/netbeans/jmx/build.xml --- a/make/netbeans/jmx/build.xml Thu Sep 10 17:56:24 2015 +0200 +++ b/make/netbeans/jmx/build.xml Thu Sep 10 14:55:20 2015 -0700 @@ -63,8 +63,8 @@ - @@ -90,44 +90,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 4b948e5a3e77 -r 7ecf45f5fa46 make/rmic/Rmic-java.management.gmk --- a/make/rmic/Rmic-java.management.gmk Thu Sep 10 17:56:24 2015 +0200 +++ b/make/rmic/Rmic-java.management.gmk Thu Sep 10 14:55:20 2015 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, 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 @@ -32,38 +32,31 @@ # Generate RMI stubs # -# For RMI/IIOP call rmic a second time with -standardPackage option -# so that *_tie classes are generated in package without the prefix -# org.omg.stub (6375696) JMX_RMI_CLASSES := javax.management.remote.rmi.RMIConnectionImpl \ javax.management.remote.rmi.RMIServerImpl -GENRMIIIOPCLASSES := -ifneq ($(RMICONNECTOR_IIOP), false) - GENRMIIIOPCLASSES := $(RMICONNECTOR_IIOP) -endif -$(eval $(call SetupRMICompilation,RMI_IIOP, \ + +# Generate into gensrc dir where sources get picked up for javadoc, then move the classes +# into the stub classes dir. +$(eval $(call SetupRMICompilation,RMI_GEN, \ CLASSES := $(JMX_RMI_CLASSES), \ CLASSES_DIR := $(CLASSES_DIR)/java.management, \ - STUB_CLASSES_DIR := $(STUB_CLASSES_DIR)/java.management, \ + STUB_CLASSES_DIR := $(RMIC_GENSRC_DIR), \ RUN_V12 := true, \ - RUN_IIOP := $(GENRMIIIOPCLASSES), \ - RUN_IIOP_STDPKG := $(GENRMIIIOPCLASSES))) + KEEP_GENERATED := true, \ +)) -# Keep generated RMI/JRMP Stub source files and copy them to RMIC_GENSRC_DIR -# so that javadoc can include them in the API (4997471) -$(eval $(call SetupRMICompilation,RMI_SRC, \ - CLASSES := $(JMX_RMI_CLASSES), \ - CLASSES_DIR := $(CLASSES_DIR)/java.management, \ - STUB_CLASSES_DIR := $(RMIC_GENSRC_DIR)/java.management, \ - RUN_V12 := true, \ - KEEP_GENERATED := true)) +# Find all classes generated and move them from the gensrc dir to the stub classes dir +$(RMIC_GENSRC_DIR)/_classes.moved: $(RMI_GEN) + $(eval classfiles := $(shell $(FIND) $(RMIC_GENSRC_DIR) -name "*.class")) + $(foreach src, $(classfiles), \ + $(eval target := $(patsubst $(RMIC_GENSRC_DIR)/%, \ + $(STUB_CLASSES_DIR)/java.management/%, $(src))) \ + $(MKDIR) -p $(dir $(target)) ; \ + $(MV) $(src) $(target) $(NEWLINE)) + $(TOUCH) $@ ########################################################################################## -$(RMIC_GENSRC_DIR)/_the.classes.removed: $(RMI_IIOP) $(RMI_SRC) - $(FIND) $(RMIC_GENSRC_DIR) -name "*.class" $(FIND_DELETE) - $(TOUCH) $@ - -all: $(RMIC_GENSRC_DIR)/_the.classes.removed $(RMI_IIOP) $(RMI_SRC) +all: $(RMIC_GENSRC_DIR)/_classes.moved $(RMI_GEN) .PHONY: all diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.base/share/classes/java/util/zip/Adler32.java --- a/src/java.base/share/classes/java/util/zip/Adler32.java Thu Sep 10 17:56:24 2015 +0200 +++ b/src/java.base/share/classes/java/util/zip/Adler32.java Thu Sep 10 14:55:20 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, 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 @@ -28,6 +28,8 @@ import java.nio.ByteBuffer; import sun.nio.ch.DirectBuffer; +import jdk.internal.HotSpotIntrinsicCandidate; + /** * A class that can be used to compute the Adler-32 checksum of a data * stream. An Adler-32 checksum is almost as reliable as a CRC-32 but @@ -126,8 +128,11 @@ } private native static int update(int adler, int b); + + @HotSpotIntrinsicCandidate private native static int updateBytes(int adler, byte[] b, int off, int len); + @HotSpotIntrinsicCandidate private native static int updateByteBuffer(int adler, long addr, int off, int len); } diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java --- a/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java Thu Sep 10 17:56:24 2015 +0200 +++ b/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java Thu Sep 10 14:55:20 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, 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 @@ -34,7 +34,7 @@ import java.util.Comparator; import java.util.stream.IntStream; -public class BasicImageReader { +public class BasicImageReader implements AutoCloseable { private final String imagePath; private final ImageSubstrate substrate; private final ByteOrder byteOrder; diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.base/share/classes/jdk/internal/jimage/ImageNativeSubstrate.java --- a/src/java.base/share/classes/jdk/internal/jimage/ImageNativeSubstrate.java Thu Sep 10 17:56:24 2015 +0200 +++ b/src/java.base/share/classes/jdk/internal/jimage/ImageNativeSubstrate.java Thu Sep 10 14:55:20 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, 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 @@ -30,7 +30,18 @@ import sun.misc.JavaNioAccess; import sun.misc.SharedSecrets; -final class ImageNativeSubstrate implements ImageSubstrate { +public final class ImageNativeSubstrate implements ImageSubstrate { + static { + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + @Override + public Void run() { + System.loadLibrary("jimage"); + return null; + } + }); + } + private static final JavaNioAccess NIOACCESS = SharedSecrets.getJavaNioAccess(); @@ -52,6 +63,20 @@ native static long[] findAttributes(long id, byte[] path); native static int[] attributeOffsets(long id); + public native static long JIMAGE_Open(String path) throws IOException; + public native static void JIMAGE_Close(long jimageHandle); + public native static long JIMAGE_FindResource(long jimageHandle, + String moduleName, String Version, String path, + long[] size); + public native static long JIMAGE_GetResource(long jimageHandle, + long locationHandle, byte[] buffer, long size); + // Get an array of names that match; return the count found upto array size + public native static int JIMAGE_Resources(long jimageHandle, + String[] outputNames); + // Return the module name for the package + public native static String JIMAGE_PackageToModule(long imageHandle, + String packageName); + static ByteBuffer newDirectByteBuffer(long address, long capacity) { assert capacity < Integer.MAX_VALUE; return NIOACCESS.newDirectByteBuffer(address, (int)capacity, null); diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.base/share/native/include/jvm.h --- a/src/java.base/share/native/include/jvm.h Thu Sep 10 17:56:24 2015 +0200 +++ b/src/java.base/share/native/include/jvm.h Thu Sep 10 14:55:20 2015 -0700 @@ -557,48 +557,6 @@ JVM_SupportsCX8(void); /* - * jdk.internal.jimage - */ - -JNIEXPORT jlong JNICALL -JVM_ImageOpen(JNIEnv *env, const char *nativePath, jboolean big_endian); - -JNIEXPORT void JNICALL -JVM_ImageClose(JNIEnv *env, jlong id); - -JNIEXPORT jlong JNICALL -JVM_ImageGetIndexAddress(JNIEnv *env, jlong id); - -JNIEXPORT jlong JNICALL -JVM_ImageGetDataAddress(JNIEnv *env,jlong id); - -JNIEXPORT jboolean JNICALL -JVM_ImageRead(JNIEnv *env, jlong id, jlong offset, - unsigned char* uncompressedAddress, jlong uncompressed_size); - -JNIEXPORT jboolean JNICALL -JVM_ImageReadCompressed(JNIEnv *env, jlong id, jlong offset, - unsigned char* compressedBuffer, jlong compressed_size, - unsigned char* uncompressedBuffer, jlong uncompressed_size); - -JNIEXPORT const char* JNICALL -JVM_ImageGetStringBytes(JNIEnv *env, jlong id, jint offset); - -JNIEXPORT jlong* JNICALL -JVM_ImageGetAttributes(JNIEnv *env, jlong* rawAttributes, jlong id, jint offset); - -JNIEXPORT jsize JNICALL -JVM_ImageGetAttributesCount(JNIEnv *env); - -JNIEXPORT jlong* JNICALL -JVM_ImageFindAttributes(JNIEnv *env, jlong* rawAttributes, jbyte* rawBytes, jsize size, jlong id); - -JNIEXPORT jint* JNICALL -JVM_ImageAttributeOffsets(JNIEnv *env, jint* rawOffsets, unsigned int length, jlong id); - -JNIEXPORT unsigned int JNICALL -JVM_ImageAttributeOffsetsLength(JNIEnv *env, jlong id); -/* * com.sun.dtrace.jsdt support */ diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.base/share/native/libjava/Image.c --- a/src/java.base/share/native/libjava/Image.c Thu Sep 10 17:56:24 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2015, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 - -#include "jni.h" -#include "jvm.h" -#include "jdk_internal_jimage_ImageNativeSubstrate.h" - -JNIEXPORT jlong JNICALL -Java_jdk_internal_jimage_ImageNativeSubstrate_openImage(JNIEnv *env, - jclass cls, jstring path, jboolean big_endian) { - const char *nativePath; - jlong ret; - - nativePath = (*env)->GetStringUTFChars(env, path, NULL); - ret = JVM_ImageOpen(env, nativePath, big_endian); - (*env)->ReleaseStringUTFChars(env, path, nativePath); - return ret; -} - -JNIEXPORT void JNICALL -Java_jdk_internal_jimage_ImageNativeSubstrate_closeImage(JNIEnv *env, - jclass cls, jlong id) { - JVM_ImageClose(env, id); -} - -JNIEXPORT jlong JNICALL -Java_jdk_internal_jimage_ImageNativeSubstrate_getIndexAddress(JNIEnv *env, - jclass cls, jlong id) { - return JVM_ImageGetIndexAddress(env, id); -} - -JNIEXPORT jlong JNICALL -Java_jdk_internal_jimage_ImageNativeSubstrate_getDataAddress(JNIEnv *env, - jclass cls, jlong id) { - return JVM_ImageGetDataAddress(env, id); -} - -JNIEXPORT jboolean JNICALL -Java_jdk_internal_jimage_ImageNativeSubstrate_read(JNIEnv *env, - jclass cls, jlong id, jlong offset, - jobject uncompressedBuffer, jlong uncompressed_size) { - unsigned char* uncompressedAddress; - - uncompressedAddress = (unsigned char*) (*env)->GetDirectBufferAddress(env, uncompressedBuffer); - if (uncompressedBuffer == NULL) { - return JNI_FALSE; - } - return JVM_ImageRead(env, id, offset, uncompressedAddress, uncompressed_size); -} - -JNIEXPORT jboolean JNICALL -Java_jdk_internal_jimage_ImageNativeSubstrate_readCompressed(JNIEnv *env, - jclass cls, jlong id, jlong offset, - jobject compressedBuffer, jlong compressed_size, - jobject uncompressedBuffer, jlong uncompressed_size) { - // Get address of read direct buffer. - unsigned char* compressedAddress; - unsigned char* uncompressedAddress; - - compressedAddress = (unsigned char*) (*env)->GetDirectBufferAddress(env, compressedBuffer); - // Get address of decompression direct buffer. - uncompressedAddress = (unsigned char*) (*env)->GetDirectBufferAddress(env, uncompressedBuffer); - if (uncompressedBuffer == NULL || compressedBuffer == NULL) { - return JNI_FALSE; - } - return JVM_ImageReadCompressed(env, id, offset, compressedAddress, compressed_size, - uncompressedAddress, uncompressed_size); -} - -JNIEXPORT jbyteArray JNICALL -Java_jdk_internal_jimage_ImageNativeSubstrate_getStringBytes(JNIEnv *env, - jclass cls, jlong id, jint offset) { - const char* data; - size_t size; - jbyteArray byteArray; - jbyte* rawBytes; - - data = JVM_ImageGetStringBytes(env, id, offset); - // Determine String length. - size = strlen(data); - // Allocate byte array. - byteArray = (*env)->NewByteArray(env, (jsize) size); - if (byteArray == NULL) { - return NULL; - } - // Get array base address. - rawBytes = (*env)->GetByteArrayElements(env, byteArray, NULL); - // Copy bytes from image string table. - memcpy(rawBytes, data, size); - // Release byte array base address. - (*env)->ReleaseByteArrayElements(env, byteArray, rawBytes, 0); - return byteArray; -} - -JNIEXPORT jlongArray JNICALL -Java_jdk_internal_jimage_ImageNativeSubstrate_getAttributes(JNIEnv *env, - jclass cls, jlong id, jint offset) { - // Allocate a jlong large enough for all location attributes. - jlongArray attributes; - jlong* rawAttributes; - jlong* ret; - - attributes = (*env)->NewLongArray(env, JVM_ImageGetAttributesCount(env)); - if (attributes == NULL) { - return NULL; - } - // Get base address for jlong array. - rawAttributes = (*env)->GetLongArrayElements(env, attributes, NULL); - ret = JVM_ImageGetAttributes(env, rawAttributes, id, offset); - // Release jlong array base address. - (*env)->ReleaseLongArrayElements(env, attributes, rawAttributes, 0); - return ret == NULL ? NULL : attributes; -} - -JNIEXPORT jlongArray JNICALL -Java_jdk_internal_jimage_ImageNativeSubstrate_findAttributes(JNIEnv *env, - jclass cls, jlong id, jbyteArray utf8) { - // Allocate a jlong large enough for all location attributes. - jsize count; - jlongArray attributes; - jlong* rawAttributes; - jsize size; - jbyte* rawBytes; - jlong* ret; - - count = JVM_ImageGetAttributesCount(env); - attributes = (*env)->NewLongArray(env, JVM_ImageGetAttributesCount(env)); - if (attributes == NULL) { - return NULL; - } - // Get base address for jlong array. - rawAttributes = (*env)->GetLongArrayElements(env, attributes, NULL); - size = (*env)->GetArrayLength(env, utf8); - rawBytes = (*env)->GetByteArrayElements(env, utf8, NULL); - ret = JVM_ImageFindAttributes(env, rawAttributes, rawBytes, size, id); - (*env)->ReleaseByteArrayElements(env, utf8, rawBytes, 0); - // Release jlong array base address. - (*env)->ReleaseLongArrayElements(env, attributes, rawAttributes, 0); - return ret == NULL ? NULL : attributes; - -} - -JNIEXPORT jintArray JNICALL -Java_jdk_internal_jimage_ImageNativeSubstrate_attributeOffsets(JNIEnv *env, - jclass cls, jlong id) { - unsigned int length; - jintArray offsets; - jint* rawOffsets; - jint* ret; - - length = JVM_ImageAttributeOffsetsLength(env, id); - offsets = (*env)->NewIntArray(env, length); - if (offsets == NULL) { - return NULL; - } - // Get base address of result. - rawOffsets = (*env)->GetIntArrayElements(env, offsets, NULL); - ret = JVM_ImageAttributeOffsets(env, rawOffsets, length, id); - if (length == 0) { - return NULL; - } - // Release result base address. - (*env)->ReleaseIntArrayElements(env, offsets, rawOffsets, 0); - return ret == NULL ? NULL : offsets; -} diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp Thu Sep 10 14:55:20 2015 -0700 @@ -0,0 +1,598 @@ +/* + * Copyright (c) 2015, 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 + +#include "jni.h" +#include "jni_util.h" +#include "jdk_util.h" +#include "endian.hpp" +#include "imageDecompressor.hpp" +#include "imageFile.hpp" +#include "inttypes.hpp" +#include "jimage.hpp" +#include "osSupport.hpp" + +#include "jdk_internal_jimage_ImageNativeSubstrate.h" + +extern bool MemoryMapImage; + +// jdk.internal.jimage ///////////////////////////////////////////////////////// + +// Java entry to open an image file for sharing. + +static jlong JIMAGE_Open(JNIEnv *env, const char *nativePath, jboolean big_endian) { + // Open image file for reading. + ImageFileReader* reader = ImageFileReader::open(nativePath, big_endian != JNI_FALSE); + // Return image ID as a jlong. + return ImageFileReader::readerToID(reader); +} + +// Java entry for closing a shared image file. + +static void JIMAGE_Close(JNIEnv *env, jlong id) { + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id); + // If valid reader the close. + if (reader != NULL) { + ImageFileReader::close(reader); + } +} + +// Java entry for accessing the base address of the image index. + +static jlong JIMAGE_GetIndexAddress(JNIEnv *env, jlong id) { + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id); + // If valid reader return index base address (as jlong) else zero. + return reader != NULL ? (jlong) reader->get_index_address() : 0L; +} + +// Java entry for accessing the base address of the image data. + +static jlong JIMAGE_GetDataAddress(JNIEnv *env, jlong id) { + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id); + // If valid reader return data base address (as jlong) else zero. + return MemoryMapImage && reader != NULL ? (jlong) reader->get_data_address() : 0L; +} + +// Java entry for reading an uncompressed resource from the image. + +static jboolean JIMAGE_Read(JNIEnv *env, jlong id, jlong offset, + unsigned char* uncompressedAddress, jlong uncompressed_size) { + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id);\ + // If not a valid reader the fail the read. + if (reader == NULL) return false; + // Get the file offset of resource data. + u8 file_offset = reader->get_index_size() + offset; + // Check validity of arguments. + if (offset < 0 || + uncompressed_size < 0 || + file_offset > reader->file_size() - uncompressed_size) { + return false; + } + // Read file content into buffer. + return (jboolean) reader->read_at((u1*) uncompressedAddress, uncompressed_size, + file_offset); +} + +// Java entry for reading a compressed resource from the image. + +static jboolean JIMAGE_ReadCompressed(JNIEnv *env, + jlong id, jlong offset, + unsigned char* compressedAddress, jlong compressed_size, + unsigned char* uncompressedAddress, jlong uncompressed_size) { + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id); + // If not a valid reader the fail the read. + if (reader == NULL) return false; + // Get the file offset of resource data. + u8 file_offset = reader->get_index_size() + offset; + // Check validity of arguments. + if (offset < 0 || + compressed_size < 0 || + uncompressed_size < 0 || + file_offset > reader->file_size() - compressed_size) { + return false; + } + + // Read file content into buffer. + bool is_read = reader->read_at(compressedAddress, compressed_size, + file_offset); + // If successfully read then decompress. + if (is_read) { + const ImageStrings strings = reader->get_strings(); + ImageDecompressor::decompress_resource(compressedAddress, uncompressedAddress, + (u4) uncompressed_size, &strings); + } + return (jboolean) is_read; +} + +// Java entry for retrieving UTF-8 bytes from image string table. + +static const char* JIMAGE_GetStringBytes(JNIEnv *env, jlong id, jint offset) { + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id); + // Fail if not valid reader. + if (reader == NULL) return NULL; + // Manage image string table. + ImageStrings strings = reader->get_strings(); + // Retrieve string adrress from table. + const char* data = strings.get(offset); + return data; +} + +// Utility function to copy location information into a jlong array. +// WARNING: This function is experimental and temporary during JDK 9 development +// cycle. It will not be supported in the eventual JDK 9 release. + +static void image_expand_location(JNIEnv *env, jlong* rawAttributes, ImageLocation& location) { + // Copy attributes from location. + for (int kind = ImageLocation::ATTRIBUTE_END + 1; + kind < ImageLocation::ATTRIBUTE_COUNT; + kind++) { + rawAttributes[kind] = location.get_attribute(kind); + } +} + +// Java entry for retrieving location attributes for attribute offset. + +static jlong* JIMAGE_GetAttributes(JNIEnv *env, jlong* rawAttributes, jlong id, jint offset) { + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id); + // Fail if not valid reader. + if (reader == NULL) return NULL; + // Retrieve first byte address of resource's location attribute stream. + u1* data = reader->get_location_offset_data(offset); + // Fail if not valid offset. + if (data == NULL) return NULL; + // Expand stream into array. + ImageLocation location(data); + image_expand_location(env, rawAttributes, location); + return rawAttributes; +} + +// Java entry for retrieving location attributes count for attribute offset. + +static jsize JIMAGE_GetAttributesCount(JNIEnv *env) { + return ImageLocation::ATTRIBUTE_COUNT; +} + +// Java entry for retrieving location attributes for named resource. + +static jlong* JIMAGE_FindAttributes(JNIEnv *env, jlong* rawAttributes, jbyte* rawBytes, jsize size, jlong id) { + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id); + // Fail if not valid reader. + if (reader == NULL) return NULL; + // Convert byte array to a cstring. + char* path = new char[size + 1]; + memcpy(path, rawBytes, size); + path[size] = '\0'; + // Locate resource location data. + ImageLocation location; + bool found = reader->find_location(path, location); + delete path; + // Resource not found. + if (!found) return NULL; + // Expand stream into array. + image_expand_location(env, rawAttributes, location); + return rawAttributes; +} + +// Java entry for retrieving all the attribute stream offsets from an image. + +static jint* JIMAGE_AttributeOffsets(JNIEnv *env, jint* rawOffsets, unsigned int length, jlong id) { + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id); + // Fail if not valid reader. + if (reader == NULL) return NULL; + // Determine endian for reader. + Endian* endian = reader->endian(); + // Get base address of attribute stream offsets table. + u4* offsets_table = reader->offsets_table(); + // Allocate int array result. + // Copy values to result (converting endian.) + for (u4 i = 0; i < length; i++) { + rawOffsets[i] = endian->get(offsets_table[i]); + } + return rawOffsets; +} + +// Java entry for retrieving all the attribute stream offsets length from an image. + +static unsigned int JIMAGE_AttributeOffsetsLength(JNIEnv *env, jlong id) { + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id); + // Fail if not valid reader. + if (reader == NULL) return 0; + // Get perfect hash table length. + u4 length = reader->table_length(); + return (jint) length; +} + +JNIEXPORT jint JNICALL +JNI_OnLoad(JavaVM *vm, void *reserved) { + JNIEnv *env; + + if (vm->GetEnv((void**) &env, JNI_VERSION_1_2) != JNI_OK) { + return JNI_EVERSION; /* JNI version not supported */ + } + + return JNI_VERSION_1_2; +} + +JNIEXPORT jlong JNICALL +Java_jdk_internal_jimage_ImageNativeSubstrate_openImage(JNIEnv *env, + jclass cls, jstring path, jboolean big_endian) { + const char *nativePath; + jlong ret; + + nativePath = env->GetStringUTFChars(path, NULL); + ret = JIMAGE_Open(env, nativePath, big_endian); + env->ReleaseStringUTFChars(path, nativePath); + return ret; +} + +JNIEXPORT void JNICALL +Java_jdk_internal_jimage_ImageNativeSubstrate_closeImage(JNIEnv *env, + jclass cls, jlong id) { + JIMAGE_Close(env, id); +} + +JNIEXPORT jlong JNICALL +Java_jdk_internal_jimage_ImageNativeSubstrate_getIndexAddress(JNIEnv *env, + jclass cls, jlong id) { + return JIMAGE_GetIndexAddress(env, id); +} + +JNIEXPORT jlong JNICALL +Java_jdk_internal_jimage_ImageNativeSubstrate_getDataAddress(JNIEnv *env, + jclass cls, jlong id) { + return JIMAGE_GetDataAddress(env, id); +} + +JNIEXPORT jboolean JNICALL +Java_jdk_internal_jimage_ImageNativeSubstrate_read(JNIEnv *env, + jclass cls, jlong id, jlong offset, + jobject uncompressedBuffer, jlong uncompressed_size) { + unsigned char* uncompressedAddress; + + uncompressedAddress = (unsigned char*) env->GetDirectBufferAddress(uncompressedBuffer); + if (uncompressedAddress == NULL) { + return JNI_FALSE; + } + return JIMAGE_Read(env, id, offset, uncompressedAddress, uncompressed_size); +} + +JNIEXPORT jboolean JNICALL +Java_jdk_internal_jimage_ImageNativeSubstrate_readCompressed(JNIEnv *env, + jclass cls, jlong id, jlong offset, + jobject compressedBuffer, jlong compressed_size, + jobject uncompressedBuffer, jlong uncompressed_size) { + // Get address of read direct buffer. + unsigned char* compressedAddress; + unsigned char* uncompressedAddress; + + compressedAddress = (unsigned char*) env->GetDirectBufferAddress(compressedBuffer); + // Get address of decompression direct buffer. + uncompressedAddress = (unsigned char*) env->GetDirectBufferAddress(uncompressedBuffer); + if (compressedAddress == NULL || uncompressedAddress == NULL) { + return JNI_FALSE; + } + return JIMAGE_ReadCompressed(env, id, offset, compressedAddress, compressed_size, + uncompressedAddress, uncompressed_size); +} + +JNIEXPORT jbyteArray JNICALL +Java_jdk_internal_jimage_ImageNativeSubstrate_getStringBytes(JNIEnv *env, + jclass cls, jlong id, jint offset) { + const char* data; + size_t size; + jbyteArray byteArray; + jbyte* rawBytes; + + data = JIMAGE_GetStringBytes(env, id, offset); + // Determine String length. + size = strlen(data); + // Allocate byte array. + byteArray = env->NewByteArray((jsize) size); + if (byteArray == NULL) { + return NULL; + } + // Get array base address. + rawBytes = env->GetByteArrayElements(byteArray, NULL); + // Copy bytes from image string table. + memcpy(rawBytes, data, size); + // Release byte array base address. + env->ReleaseByteArrayElements(byteArray, rawBytes, 0); + return byteArray; +} + +JNIEXPORT jlongArray JNICALL +Java_jdk_internal_jimage_ImageNativeSubstrate_getAttributes(JNIEnv *env, + jclass cls, jlong id, jint offset) { + // Allocate a jlong large enough for all location attributes. + jlongArray attributes; + jlong* rawAttributes; + jlong* ret; + + attributes = env->NewLongArray(JIMAGE_GetAttributesCount(env)); + if (attributes == NULL) { + return NULL; + } + // Get base address for jlong array. + rawAttributes = env->GetLongArrayElements(attributes, NULL); + ret = JIMAGE_GetAttributes(env, rawAttributes, id, offset); + // Release jlong array base address. + env->ReleaseLongArrayElements(attributes, rawAttributes, 0); + return ret == NULL ? NULL : attributes; +} + +JNIEXPORT jlongArray JNICALL +Java_jdk_internal_jimage_ImageNativeSubstrate_findAttributes(JNIEnv *env, + jclass cls, jlong id, jbyteArray utf8) { + // Allocate a jlong large enough for all location attributes. + jsize count; + jlongArray attributes; + jlong* rawAttributes; + jsize size; + jbyte* rawBytes; + jlong* ret; + + count = JIMAGE_GetAttributesCount(env); + attributes = env->NewLongArray(JIMAGE_GetAttributesCount(env)); + if (attributes == NULL) { + return NULL; + } + // Get base address for jlong array. + rawAttributes = env->GetLongArrayElements(attributes, NULL); + size = env->GetArrayLength(utf8); + rawBytes = env->GetByteArrayElements(utf8, NULL); + ret = JIMAGE_FindAttributes(env, rawAttributes, rawBytes, size, id); + env->ReleaseByteArrayElements(utf8, rawBytes, 0); + // Release jlong array base address. + env->ReleaseLongArrayElements(attributes, rawAttributes, 0); + return ret == NULL ? NULL : attributes; + +} + +JNIEXPORT jintArray JNICALL +Java_jdk_internal_jimage_ImageNativeSubstrate_attributeOffsets(JNIEnv *env, + jclass cls, jlong id) { + unsigned int length; + jintArray offsets; + jint* rawOffsets; + jint* ret; + + length = JIMAGE_AttributeOffsetsLength(env, id); + offsets = env->NewIntArray(length); + if (offsets == NULL) { + return NULL; + } + // Get base address of result. + rawOffsets = env->GetIntArrayElements(offsets, NULL); + ret = JIMAGE_AttributeOffsets(env, rawOffsets, length, id); + if (length == 0) { + return NULL; + } + // Release result base address. + env->ReleaseIntArrayElements(offsets, rawOffsets, 0); + return ret == NULL ? NULL : offsets; +} + +/* + * Class: jdk_internal_jimage_ImageNativeSubstrate + * Method: JIMAGE_open + * Signature: (Ljava/lang/String;)J + */ +JNIEXPORT jlong JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Open +(JNIEnv *env, jclass, jstring path) { + const char *nativePath = env->GetStringUTFChars(path, NULL); + if (nativePath == NULL) + return 0; // Exception already thrown + jint error; + jlong ret = (jlong) JIMAGE_Open(nativePath, &error); + env->ReleaseStringUTFChars(path, nativePath); + return ret; +} + +/* + * Class: jdk_internal_jimage_ImageNativeSubstrate + * Method: JIMAGE_Close + * Signature: (J)J + */ +JNIEXPORT void JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Close +(JNIEnv *env, jclass, jlong jimageHandle) { + JIMAGE_Close((JImageFile*) jimageHandle); +} + +/* + * Class: jdk_internal_jimage_ImageNativeSubstrate + * Method: JIMAGE_FindResource + * Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[J)J + */ +JNIEXPORT jlong JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1FindResource +(JNIEnv *env, jclass, jlong jimageHandle, jstring moduleName, + jstring version, jstring path, jlongArray output_size) { + const char *native_module = NULL; + const char *native_version = NULL; + const char *native_path = NULL; + jlong * native_array = NULL; + jlong size = 0; + jlong ret = 0; + + do { + native_module = env->GetStringUTFChars(moduleName, NULL); + if (native_module == NULL) + break; + native_version = env->GetStringUTFChars(version, NULL); + if (native_version == NULL) + break; + native_path = env->GetStringUTFChars(path, NULL); + if (native_path == NULL) + break; + if (env->GetArrayLength(output_size) < 1) + break; + // Get base address for jlong array. + native_array = env->GetLongArrayElements(output_size, NULL); + if (native_array == NULL) + break; + + ret = (jlong) JIMAGE_FindResource((JImageFile *) jimageHandle, + native_module, native_version, native_path, &size); + if (ret != 0) + *native_array = size; + } while (0); + + if (native_array != NULL) + env->ReleaseLongArrayElements(output_size, native_array, 0); + if (native_path != NULL) + env->ReleaseStringUTFChars(path, native_path); + if (native_version != NULL) + env->ReleaseStringUTFChars(path, native_version); + if (native_module != NULL) + env->ReleaseStringUTFChars(path, native_module); + + return ret; +} + +/* + * Class: jdk_internal_jimage_ImageNativeSubstrate + * Method: JIMAGE_GetResource + * Signature: (JJ[BJ)J + */ +JNIEXPORT jlong JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1GetResource +(JNIEnv *env, jclass, jlong jimageHandle, jlong jlocationHandle, jbyteArray buffer, jlong size) { + jbyte * native_buffer = NULL; + jlong actual_size = 0; + do { + if (env->GetArrayLength(buffer) < size) + break; + + native_buffer = env->GetByteArrayElements(buffer, NULL); + if (native_buffer == NULL) + break; + + actual_size = JIMAGE_GetResource((JImageFile*) jimageHandle, + (JImageLocationRef) jlocationHandle, + (char *) native_buffer, size); + } while (0); + // Release byte array + if (native_buffer != NULL) + env->ReleaseByteArrayElements(buffer, native_buffer, 0); + + return actual_size; +} + +// Structure passed from iterator to a visitor to accumulate the results + +struct VisitorData { + JNIEnv *env; + int size; // current number of strings + int max; // Maximum number of strings + jobjectArray array; // String array to store the strings +}; + +// Visitor to accumulate fully qualified resource names + +static bool resourceVisitor(JImageFile* image, + const char* module, const char* version, const char* package, + const char* name, const char* extension, void* arg) { + struct VisitorData *vdata = (struct VisitorData *) arg; + JNIEnv* env = vdata->env; + if (vdata->size < vdata->max) { + // Store if there is room in the array + // Concatenate to get full path + char fullpath[IMAGE_MAX_PATH]; + fullpath[0] = '\0'; + if (*module != '\0') { + strncpy(fullpath, "/", IMAGE_MAX_PATH - 1); + strncat(fullpath, module, IMAGE_MAX_PATH - 1); + strncat(fullpath, "/", IMAGE_MAX_PATH - 1); + } + if (*package != '\0') { + strncat(fullpath, package, IMAGE_MAX_PATH - 1); + strncat(fullpath, "/", IMAGE_MAX_PATH - 1); + } + strncat(fullpath, name, IMAGE_MAX_PATH - 1); + if (*extension != '\0') { + strncat(fullpath, ".", IMAGE_MAX_PATH - 1); + strncat(fullpath, extension, IMAGE_MAX_PATH - 1); + } + jobject str = env->NewStringUTF(fullpath); + JNU_CHECK_EXCEPTION_RETURN(env, true); + env->SetObjectArrayElement(vdata->array, vdata->size, str); + JNU_CHECK_EXCEPTION_RETURN(env, true); + } + vdata->size++; // always count so the total size is returned + return true; +} + +/* + * Class: jdk_internal_jimage_ImageNativeSubstrate + * Method: JIMAGE_Resources + * Signature: (J)V + */ +JNIEXPORT jint JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Resources +(JNIEnv *env, jclass, jlong jimageHandle, + jobjectArray outputNames) { + struct VisitorData vdata; + vdata.env = env; + vdata.max = 0; + vdata.size = 0; + vdata.array = outputNames; + + vdata.max = (outputNames != NULL) ? env->GetArrayLength(outputNames) : 0; + JIMAGE_ResourceIterator((JImageFile*) jimageHandle, &resourceVisitor, &vdata); + return vdata.size; +} + +/* + * Class: jdk_internal_jimage_ImageNativeSubstrate + * Method: JIMAGE_PackageToModule + * Signature: (JLjava/lang/String;)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1PackageToModule +(JNIEnv *env, jclass, jlong jimageHandle, jstring package_name) { + const char *native_package = NULL; + const char *native_module = NULL; + jstring module = NULL; + + native_package = env->GetStringUTFChars(package_name, NULL); + JNU_CHECK_EXCEPTION_RETURN(env, NULL); + + native_module = JIMAGE_PackageToModule((JImageFile*) jimageHandle, native_package); + if (native_module != NULL) { + module = env->NewStringUTF(native_module); + } + env->ReleaseStringUTFChars(package_name, native_package); + return module; +} + +JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { + ImageDecompressor::image_decompressor_close(); +} diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.base/share/native/libjimage/endian.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/native/libjimage/endian.cpp Thu Sep 10 14:55:20 2015 -0700 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2015, 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 "endian.hpp" +#include "inttypes.hpp" + +// Most modern compilers optimize the bswap routines to native instructions. +inline static u2 bswap_16(u2 x) { + return ((x & 0xFF) << 8) | + ((x >> 8) & 0xFF); +} + +inline static u4 bswap_32(u4 x) { + return ((x & 0xFF) << 24) | + ((x & 0xFF00) << 8) | + ((x >> 8) & 0xFF00) | + ((x >> 24) & 0xFF); +} + +inline static u8 bswap_64(u8 x) { + return (u8)bswap_32((u4)x) << 32 | + (u8)bswap_32((u4)(x >> 32)); +} + +u2 NativeEndian::get(u2 x) { return x; } +u4 NativeEndian::get(u4 x) { return x; } +u8 NativeEndian::get(u8 x) { return x; } +s2 NativeEndian::get(s2 x) { return x; } +s4 NativeEndian::get(s4 x) { return x; } +s8 NativeEndian::get(s8 x) { return x; } + +void NativeEndian::set(u2& x, u2 y) { x = y; } +void NativeEndian::set(u4& x, u4 y) { x = y; } +void NativeEndian::set(u8& x, u8 y) { x = y; } +void NativeEndian::set(s2& x, s2 y) { x = y; } +void NativeEndian::set(s4& x, s4 y) { x = y; } +void NativeEndian::set(s8& x, s8 y) { x = y; } + +NativeEndian NativeEndian::_native; + +u2 SwappingEndian::get(u2 x) { return bswap_16(x); } +u4 SwappingEndian::get(u4 x) { return bswap_32(x); } +u8 SwappingEndian::get(u8 x) { return bswap_64(x); } +s2 SwappingEndian::get(s2 x) { return bswap_16(x); } +s4 SwappingEndian::get(s4 x) { return bswap_32(x); } +s8 SwappingEndian::get(s8 x) { return bswap_64(x); } + +void SwappingEndian::set(u2& x, u2 y) { x = bswap_16(y); } +void SwappingEndian::set(u4& x, u4 y) { x = bswap_32(y); } +void SwappingEndian::set(u8& x, u8 y) { x = bswap_64(y); } +void SwappingEndian::set(s2& x, s2 y) { x = bswap_16(y); } +void SwappingEndian::set(s4& x, s4 y) { x = bswap_32(y); } +void SwappingEndian::set(s8& x, s8 y) { x = bswap_64(y); } + +SwappingEndian SwappingEndian::_swapping; + +Endian* Endian::get_handler(bool big_endian) { + // If requesting little endian on a little endian machine or + // big endian on a big endian machine use native handler + if (big_endian == is_big_endian()) { + return NativeEndian::get_native(); + } else { + // Use swapping handler. + return SwappingEndian::get_swapping(); + } +} + +// Return a platform u2 from an array in which Big Endian is applied. +u2 Endian::get_java(u1* x) { + return (u2) (x[0]<<8 | x[1]); +} + +// Add a platform u2 to the array as a Big Endian u2 +void Endian::set_java(u1* p, u2 x) { + p[0] = (x >> 8) & 0xff; + p[1] = x & 0xff; +} + +Endian* Endian::get_native_handler() { + return NativeEndian::get_native(); +} diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.base/share/native/libjimage/endian.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/native/libjimage/endian.hpp Thu Sep 10 14:55:20 2015 -0700 @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2015, 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. + * + */ + +#ifndef LIBJIMAGE_ENDIAN_HPP +#define LIBJIMAGE_ENDIAN_HPP + +#include "inttypes.hpp" + +// Selectable endian handling. Endian handlers are used when accessing values +// that are of unknown (until runtime) endian. The only requirement of the values +// accessed are that they are aligned to proper size boundaries (no misalignment.) +// To select an endian handler, one should call Endian::get_handler(big_endian); +// Where big_endian is true if big endian is required and false otherwise. The +// native endian handler can be fetched with Endian::get_native_handler(); +// To retrieve a value using the approprate endian, use one of the overloaded +// calls to get. To set a value, then use one of the overloaded set calls. +// Ex. +// s4 value; // Imported value; +// ... +// Endian* endian = Endian::get_handler(true); // Use big endian +// s4 corrected = endian->get(value); +// endian->set(value, 1); +// +class Endian { +public: + virtual u2 get(u2 x) = 0; + virtual u4 get(u4 x) = 0; + virtual u8 get(u8 x) = 0; + virtual s2 get(s2 x) = 0; + virtual s4 get(s4 x) = 0; + virtual s8 get(s8 x) = 0; + + virtual void set(u2& x, u2 y) = 0; + virtual void set(u4& x, u4 y) = 0; + virtual void set(u8& x, u8 y) = 0; + virtual void set(s2& x, s2 y) = 0; + virtual void set(s4& x, s4 y) = 0; + virtual void set(s8& x, s8 y) = 0; + + // Quick little endian test. + static bool is_little_endian() { u4 x = 1; return *(u1 *)&x != 0; } + + // Quick big endian test. + static bool is_big_endian() { return !is_little_endian(); } + + // Select an appropriate endian handler. + static Endian* get_handler(bool big_endian); + + // Return the native endian handler. + static Endian* get_native_handler(); + + // get platform u2 from Java Big endian + static u2 get_java(u1* x); + // set platform u2 to Java Big endian + static void set_java(u1* p, u2 x); +}; + +// Normal endian handling. +class NativeEndian : public Endian { +private: + static NativeEndian _native; + +public: + u2 get(u2 x); + u4 get(u4 x); + u8 get(u8 x); + s2 get(s2 x); + s4 get(s4 x); + s8 get(s8 x); + + void set(u2& x, u2 y); + void set(u4& x, u4 y); + void set(u8& x, u8 y); + void set(s2& x, s2 y); + void set(s4& x, s4 y); + void set(s8& x, s8 y); + + static Endian* get_native() { return &_native; } +}; + +// Swapping endian handling. +class SwappingEndian : public Endian { +private: + static SwappingEndian _swapping; + +public: + u2 get(u2 x); + u4 get(u4 x); + u8 get(u8 x); + s2 get(s2 x); + s4 get(s4 x); + s8 get(s8 x); + + void set(u2& x, u2 y); + void set(u4& x, u4 y); + void set(u8& x, u8 y); + void set(s2& x, s2 y); + void set(s4& x, s4 y); + void set(s8& x, s8 y); + + static Endian* get_swapping() { return &_swapping; } +}; +#endif // LIBJIMAGE_ENDIAN_HPP diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.base/share/native/libjimage/imageDecompressor.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/native/libjimage/imageDecompressor.cpp Thu Sep 10 14:55:20 2015 -0700 @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2015, 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" +#include "imageDecompressor.hpp" +#include "endian.hpp" +#ifdef WIN32 +#include +#else +#include +#endif + +typedef jboolean (JNICALL *ZipInflateFully_t)(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg); +static ZipInflateFully_t ZipInflateFully = NULL; + +#ifndef WIN32 + #define JNI_LIB_PREFIX "lib" + #ifdef __APPLE__ + #define JNI_LIB_SUFFIX ".dylib" + #else + #define JNI_LIB_SUFFIX ".so" + #endif +#endif + +/** + * Return the address of the entry point named in the zip shared library. + * @param name - the name of the entry point + * @return the address of the entry point or NULL + */ +static void* findEntry(const char* name) { + void *addr = NULL; +#ifdef WIN32 + HMODULE handle = GetModuleHandle("zip.dll"); + if (handle == NULL) { + return NULL; + } + addr = (void*) GetProcAddress(handle, name); + return addr; +#else + addr = dlopen(JNI_LIB_PREFIX "zip" JNI_LIB_SUFFIX, RTLD_GLOBAL|RTLD_LAZY); + if (addr == NULL) { + return NULL; + } + addr = dlsym(addr, name); + return addr; +#endif +} + +/* + * Initialize the array of decompressors. + */ +int ImageDecompressor::_decompressors_num = 0; +ImageDecompressor** ImageDecompressor::_decompressors = NULL; +void ImageDecompressor::image_decompressor_init() { + if (_decompressors == NULL) { + ZipInflateFully = (ZipInflateFully_t) findEntry("ZIP_InflateFully"); + assert(ZipInflateFully != NULL && "ZIP decompressor not found."); + _decompressors_num = 2; + _decompressors = new ImageDecompressor*[_decompressors_num]; + _decompressors[0] = new ZipDecompressor("zip"); + _decompressors[1] = new SharedStringDecompressor("compact-cp"); + } +} + +void ImageDecompressor::image_decompressor_close() { + delete _decompressors; +} + +/* + * Locate decompressor. + */ +ImageDecompressor* ImageDecompressor::get_decompressor(const char * decompressor_name) { + image_decompressor_init(); + for (int i = 0; i < _decompressors_num; i++) { + ImageDecompressor* decompressor = _decompressors[i]; + assert(decompressor != NULL && "Decompressors not initialized."); + if (strcmp(decompressor->get_name(), decompressor_name) == 0) { + return decompressor; + } + } + assert(false && "No decompressor found."); + return NULL; +} + +/* + * Decompression entry point. Called from ImageFileReader::get_resource. + */ +void ImageDecompressor::decompress_resource(u1* compressed, u1* uncompressed, + u4 uncompressed_size, const ImageStrings* strings) { + bool has_header = false; + u1* decompressed_resource = compressed; + u1* compressed_resource = compressed; + + // Resource could have been transformed by a stack of decompressors. + // Iterate and decompress resources until there is no more header. + do { + ResourceHeader _header; + memcpy(&_header, compressed_resource, sizeof (ResourceHeader)); + has_header = _header._magic == ResourceHeader::resource_header_magic; + if (has_header) { + // decompressed_resource array contains the result of decompression + decompressed_resource = new u1[_header._uncompressed_size]; + // Retrieve the decompressor name + const char* decompressor_name = strings->get(_header._decompressor_name_offset); + assert(decompressor_name && "image decompressor not found"); + // Retrieve the decompressor instance + ImageDecompressor* decompressor = get_decompressor(decompressor_name); + assert(decompressor && "image decompressor not found"); + u1* compressed_resource_base = compressed_resource; + compressed_resource += ResourceHeader::resource_header_length; + // Ask the decompressor to decompress the compressed content + decompressor->decompress_resource(compressed_resource, decompressed_resource, + &_header, strings); + if (compressed_resource_base != compressed) { + delete compressed_resource_base; + } + compressed_resource = decompressed_resource; + } + } while (has_header); + memcpy(uncompressed, decompressed_resource, uncompressed_size); + delete decompressed_resource; +} + +// Zip decompressor + +void ZipDecompressor::decompress_resource(u1* data, u1* uncompressed, + ResourceHeader* header, const ImageStrings* strings) { + char* msg = NULL; + jboolean res = ZipDecompressor::decompress(data, header->_size, uncompressed, + header->_uncompressed_size, &msg); + assert(res && "decompression failed"); +} + +jboolean ZipDecompressor::decompress(void *in, u8 inSize, void *out, u8 outSize, char **pmsg) { + return (*ZipInflateFully)(in, inSize, out, outSize, pmsg); +} + +// END Zip Decompressor + +// Shared String decompressor + +// array index is the constant pool tag. value is size. +// eg: array[5] = 8; means size of long is 8 bytes. +const u1 SharedStringDecompressor::sizes[] = {0, 0, 0, 4, 4, 8, 8, 2, 2, 4, 4, 4, 4, 0, 0, 3, 2, 0, 4}; +/** + * Recreate the class by reconstructing the constant pool. + */ +void SharedStringDecompressor::decompress_resource(u1* data, + u1* uncompressed_resource, + ResourceHeader* header, const ImageStrings* strings) { + u1* uncompressed_base = uncompressed_resource; + u1* data_base = data; + int header_size = 8; // magic + major + minor + memcpy(uncompressed_resource, data, header_size + 2); //+ cp count + uncompressed_resource += header_size + 2; + data += header_size; + u2 cp_count = Endian::get_java(data); + data += 2; + for (int i = 1; i < cp_count; i++) { + u1 tag = *data; + data += 1; + switch (tag) { + + case externalized_string: + { // String in Strings table + *uncompressed_resource = 1; + uncompressed_resource += 1; + int i = decompress_int(data); + const char * string = strings->get(i); + int str_length = (int) strlen(string); + Endian::set_java(uncompressed_resource, str_length); + uncompressed_resource += 2; + memcpy(uncompressed_resource, string, str_length); + uncompressed_resource += str_length; + break; + } + // Descriptor String has been split and types added to Strings table + case externalized_string_descriptor: + { + *uncompressed_resource = 1; + uncompressed_resource += 1; + int descriptor_index = decompress_int(data); + int indexes_length = decompress_int(data); + u1* length_address = uncompressed_resource; + uncompressed_resource += 2; + int desc_length = 0; + const char * desc_string = strings->get(descriptor_index); + if (indexes_length > 0) { + u1* indexes_base = data; + data += indexes_length; + char c = *desc_string; + do { + *uncompressed_resource = c; + uncompressed_resource++; + desc_length += 1; + /* + * Every L character is the marker we are looking at in order + * to reconstruct the descriptor. Each time an L is found, then + * we retrieve the couple token/token at the current index and + * add it to the descriptor. + * "(L;I)V" and "java/lang","String" couple of tokens, + * this becomes "(Ljava/lang/String;I)V" + */ + if (c == 'L') { + int index = decompress_int(indexes_base); + const char * pkg = strings->get(index); + int str_length = (int) strlen(pkg); + // the case where we have a package. + // reconstruct the type full name + if (str_length > 0) { + int len = str_length + 1; + char* fullpkg = new char[len]; + char* pkg_base = fullpkg; + memcpy(fullpkg, pkg, str_length); + fullpkg += str_length; + *fullpkg = '/'; + memcpy(uncompressed_resource, pkg_base, len); + uncompressed_resource += len; + delete pkg_base; + desc_length += len; + } else { // Empty package + // Nothing to do. + } + int classIndex = decompress_int(indexes_base); + const char * clazz = strings->get(classIndex); + int clazz_length = (int) strlen(clazz); + memcpy(uncompressed_resource, clazz, clazz_length); + uncompressed_resource += clazz_length; + desc_length += clazz_length; + } + desc_string += 1; + c = *desc_string; + } while (c != '\0'); + } else { + desc_length = (int) strlen(desc_string); + memcpy(uncompressed_resource, desc_string, desc_length); + uncompressed_resource += desc_length; + } + Endian::set_java(length_address, desc_length); + break; + } + + case constant_utf8: + { // UTF-8 + *uncompressed_resource = tag; + uncompressed_resource += 1; + u2 str_length = Endian::get_java(data); + int len = str_length + 2; + memcpy(uncompressed_resource, data, len); + uncompressed_resource += len; + data += len; + break; + } + + case constant_long: + case constant_double: + { + i++; + } + default: + { + *uncompressed_resource = tag; + uncompressed_resource += 1; + int size = sizes[tag]; + memcpy(uncompressed_resource, data, size); + uncompressed_resource += size; + data += size; + } + } + } + u4 remain = header->_size - (int)(data - data_base); + u4 computed = (u4)(uncompressed_resource - uncompressed_base) + remain; + if (header->_uncompressed_size != computed) + printf("Failure, expecting %d but getting %d\n", header->_uncompressed_size, + computed); + assert(header->_uncompressed_size == computed && + "Constant Pool reconstruction failed"); + memcpy(uncompressed_resource, data, remain); +} + +/* + * Decompress integers. Compressed integers are negative. + * If positive, the integer is not decompressed. + * If negative, length extracted from the first byte, then reconstruct the integer + * from the following bytes. + * Example of compression: 1 is compressed on 1 byte: 10100001 + */ +int SharedStringDecompressor::decompress_int(unsigned char*& value) { + int len = 4; + int res = 0; + char b1 = *value; + if (is_compressed((signed char)b1)) { // compressed + len = get_compressed_length(b1); + char clearedValue = b1 &= 0x1F; + if (len == 1) { + res = clearedValue; + } else { + res = (clearedValue & 0xFF) << 8 * (len - 1); + for (int i = 1; i < len; i++) { + res |= (value[i]&0xFF) << 8 * (len - i - 1); + } + } + } else { + res = (value[0] & 0xFF) << 24 | (value[1]&0xFF) << 16 | + (value[2]&0xFF) << 8 | (value[3]&0xFF); + } + value += len; + return res; +} +// END Shared String decompressor diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.base/share/native/libjimage/imageDecompressor.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/native/libjimage/imageDecompressor.hpp Thu Sep 10 14:55:20 2015 -0700 @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2015, 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. + * + */ + +#ifndef LIBJIMAGE_IMAGEDECOMPRESSOR_HPP +#define LIBJIMAGE_IMAGEDECOMPRESSOR_HPP + +#include +#include + +#include "imageFile.hpp" +#include "inttypes.hpp" +#include "jni.h" + +/* + * Compressed resources located in image have an header. + * This header contains: + * - _magic: A magic u4, required to retrieved the header in the compressed content + * - _size: The size of the compressed resource. + * - _uncompressed_size: The uncompressed size of the compressed resource. + * - _decompressor_name_offset: The ImageDecompressor instance name StringsTable offset. + * - _decompressor_config_offset: StringsTable offset of configuration that could be needed by + * the decompressor in order to decompress. + * - _is_terminal: 1: the compressed content is terminal. Uncompressing it would + * create the actual resource. 0: the compressed content is not terminal. Uncompressing it + * will result in a compressed content to be decompressed (This occurs when a stack of compressors + * have been used to compress the resource. + */ +struct ResourceHeader { + /* Length of header, needed to retrieve content offset */ + static const u1 resource_header_length = 21; + /* magic bytes that identifies a compressed resource header*/ + static const u4 resource_header_magic = 0xCAFEFAFA; + u4 _magic; // Resource header + u4 _size; // Resource size + u4 _uncompressed_size; // Expected uncompressed size + u4 _decompressor_name_offset; // Strings table decompressor offset + u4 _decompressor_config_offset; // Strings table config offset + u1 _is_terminal; // Last decompressor 1, otherwise 0. +}; + +/* + * Resources located in jimage file can be compressed. Compression occurs at + * jimage file creation time. When compressed a resource is added an header that + * contains the name of the compressor that compressed it. + * Various compression strategies can be applied to compress a resource. + * The same resource can even be compressed multiple time by a stack of compressors. + * At runtime, a resource is decompressed in a loop until there is no more header + * meaning that the resource is equivalent to the not compressed resource. + * In each iteration, the name of the compressor located in the current header + * is used to retrieve the associated instance of ImageDecompressor. + * For example “zip” is the name of the compressor that compresses resources + * using the zip algorithm. The ZipDecompressor class name is also “zip”. + * ImageDecompressor instances are retrieved from a static array in which + * they are registered. + */ +class ImageDecompressor { + +private: + const char* _name; + + /* + * Array of concrete decompressors. This array is used to retrieve the decompressor + * that can handle resource decompression. + */ + static ImageDecompressor** _decompressors; + /** + * Num of decompressors + */ + static int _decompressors_num; + /* + * Identifier of a decompressor. This name is the identification key to retrieve + * decompressor from a resource header. + */ + inline const char* get_name() const { return _name; } + + +protected: + ImageDecompressor(const char* name) : _name(name) { + } + virtual void decompress_resource(u1* data, u1* uncompressed, + ResourceHeader* header, const ImageStrings* strings) = 0; + +public: + static void image_decompressor_init(); + static void image_decompressor_close(); + static ImageDecompressor* get_decompressor(const char * decompressor_name) ; + static void decompress_resource(u1* compressed, u1* uncompressed, + u4 uncompressed_size, const ImageStrings* strings); +}; + +/** + * Zip decompressor. + */ +class ZipDecompressor : public ImageDecompressor { +public: + ZipDecompressor(const char* sym) : ImageDecompressor(sym) { } + void decompress_resource(u1* data, u1* uncompressed, ResourceHeader* header, + const ImageStrings* strings); + static jboolean decompress(void *in, u8 inSize, void *out, u8 outSize, char **pmsg); +}; + +/* + * Shared Strings decompressor. This decompressor reconstruct the class + * constant pool UTF_U entries by retrieving strings stored in jimage strings table. + * In addition, if the UTF_8 entry is a descriptor, the descriptor has to be rebuilt, + * all java type having been removed from the descriptor and added to the sting table. + * eg: "(Ljava/lang/String;I)V" ==> "(L;I)V" and "java/lang", "String" + * stored in string table. offsets to the 2 strings are compressed and stored in the + * constantpool entry. + */ +class SharedStringDecompressor : public ImageDecompressor { +private: + // the constant pool tag for UTF8 string located in strings table + static const int externalized_string = 23; + // the constant pool tag for UTF8 descriptors string located in strings table + static const int externalized_string_descriptor = 25; + // the constant pool tag for UTF8 + static const int constant_utf8 = 1; + // the constant pool tag for long + static const int constant_long = 5; + // the constant pool tag for double + static const int constant_double = 6; + // array index is the constant pool tag. value is size. + // eg: array[5] = 8; means size of long is 8 bytes. + static const u1 sizes[]; + // bit 5 and 6 are used to store the length of the compressed integer. + // size can be 1 (01), 2 (10), 3 (11). + // 0x60 ==> 0110000 + static const int compressed_index_size_mask = 0x60; + /* + * mask the length bits (5 and 6) and move to the right 5 bits. + */ + inline static int get_compressed_length(char c) { return ((char) (c & compressed_index_size_mask) >> 5); } + inline static bool is_compressed(signed char b1) { return b1 < 0; } + static int decompress_int(unsigned char*& value); +public: + SharedStringDecompressor(const char* sym) : ImageDecompressor(sym){} + void decompress_resource(u1* data, u1* uncompressed, ResourceHeader* header, + const ImageStrings* strings); +}; +#endif // LIBJIMAGE_IMAGEDECOMPRESSOR_HPP diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.base/share/native/libjimage/imageFile.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/native/libjimage/imageFile.cpp Thu Sep 10 14:55:20 2015 -0700 @@ -0,0 +1,682 @@ +/* + * Copyright (c) 2015, 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 +#include +#include + +#include "endian.hpp" +#include "imageDecompressor.hpp" +#include "imageFile.hpp" +#include "inttypes.hpp" +#include "jni.h" +#include "osSupport.hpp" + +// Map the full jimage, only with 64 bit addressing. +bool MemoryMapImage = sizeof(void *) == 8; + +#ifdef WIN32 +const char FileSeparator = '\\'; +#else +const char FileSeparator = '/'; +#endif + +// Image files are an alternate file format for storing classes and resources. The +// goal is to supply file access which is faster and smaller than the jar format. +// +// (More detailed nodes in the header.) +// + +// Compute the Perfect Hashing hash code for the supplied UTF-8 string. +s4 ImageStrings::hash_code(const char* string, s4 seed) { + // Access bytes as unsigned. + u1* bytes = (u1*)string; + // Compute hash code. + for (u1 byte = *bytes++; byte; byte = *bytes++) { + seed = (seed * HASH_MULTIPLIER) ^ byte; + } + // Ensure the result is not signed. + return seed & 0x7FFFFFFF; +} + +// Match up a string in a perfect hash table. +// Returns the index where the name should be. +// Result still needs validation for precise match (false positive.) +s4 ImageStrings::find(Endian* endian, const char* name, s4* redirect, u4 length) { + // If the table is empty, then short cut. + if (!redirect || !length) { + return NOT_FOUND; + } + // Compute the basic perfect hash for name. + s4 hash_code = ImageStrings::hash_code(name); + // Modulo table size. + s4 index = hash_code % length; + // Get redirect entry. + // value == 0 then not found + // value < 0 then -1 - value is true index + // value > 0 then value is seed for recomputing hash. + s4 value = endian->get(redirect[index]); + // if recompute is required. + if (value > 0 ) { + // Entry collision value, need to recompute hash. + hash_code = ImageStrings::hash_code(name, value); + // Modulo table size. + return hash_code % length; + } else if (value < 0) { + // Compute direct index. + return -1 - value; + } + // No entry found. + return NOT_FOUND; +} + +// Test to see if UTF-8 string begins with the start UTF-8 string. If so, +// return non-NULL address of remaining portion of string. Otherwise, return +// NULL. Used to test sections of a path without copying from image string +// table. +const char* ImageStrings::starts_with(const char* string, const char* start) { + char ch1, ch2; + // Match up the strings the best we can. + while ((ch1 = *string) && (ch2 = *start)) { + if (ch1 != ch2) { + // Mismatch, return NULL. + return NULL; + } + // Next characters. + string++, start++; + } + // Return remainder of string. + return string; +} + +// Inflates the attribute stream into individual values stored in the long +// array _attributes. This allows an attribute value to be quickly accessed by +// direct indexing. Unspecified values default to zero (from constructor.) +void ImageLocation::set_data(u1* data) { + // Deflate the attribute stream into an array of attributes. + u1 byte; + // Repeat until end header is found. + while ((byte = *data)) { + // Extract kind from header byte. + u1 kind = attribute_kind(byte); + assert(kind < ATTRIBUTE_COUNT && "invalid image location attribute"); + // Extract length of data (in bytes). + u1 n = attribute_length(byte); + // Read value (most significant first.) + _attributes[kind] = attribute_value(data + 1, n); + // Position to next attribute by skipping attribute header and data bytes. + data += n + 1; + } +} + +// Zero all attribute values. +void ImageLocation::clear_data() { + // Set defaults to zero. + memset(_attributes, 0, sizeof(_attributes)); +} + +// ImageModuleData constructor maps out sub-tables for faster access. +ImageModuleData::ImageModuleData(const ImageFileReader* image_file, + const char* module_data_name) : + _image_file(image_file), + _endian(image_file->endian()), + _strings(image_file->get_strings()) { + // Retrieve the resource containing the module data for the image file. + ImageLocation location; + bool found = image_file->find_location(module_data_name, location); + if (found) { + u8 data_size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED); + _data = new u1[(size_t)data_size]; + _image_file->get_resource(location, _data); + // Map out the header. + _header = (Header*)_data; + // Get the package to module entry count. + u4 ptm_count = _header->ptm_count(_endian); + // Get the module to package entry count. + u4 mtp_count = _header->mtp_count(_endian); + // Compute the offset of the package to module perfect hash redirect. + u4 ptm_redirect_offset = sizeof(Header); + // Compute the offset of the package to module data. + u4 ptm_data_offset = ptm_redirect_offset + ptm_count * sizeof(s4); + // Compute the offset of the module to package perfect hash redirect. + u4 mtp_redirect_offset = ptm_data_offset + ptm_count * sizeof(PTMData); + // Compute the offset of the module to package data. + u4 mtp_data_offset = mtp_redirect_offset + mtp_count * sizeof(s4); + // Compute the offset of the module to package tables. + u4 mtp_packages_offset = mtp_data_offset + mtp_count * sizeof(MTPData); + // Compute the address of the package to module perfect hash redirect. + _ptm_redirect = (s4*)(_data + ptm_redirect_offset); + // Compute the address of the package to module data. + _ptm_data = (PTMData*)(_data + ptm_data_offset); + // Compute the address of the module to package perfect hash redirect. + _mtp_redirect = (s4*)(_data + mtp_redirect_offset); + // Compute the address of the module to package data. + _mtp_data = (MTPData*)(_data + mtp_data_offset); + // Compute the address of the module to package tables. + _mtp_packages = (s4*)(_data + mtp_packages_offset); + } else { + // No module data present. + _data = NULL; + _header = NULL; + _ptm_redirect = NULL; + _ptm_data = NULL; + _mtp_redirect = NULL; + _mtp_data = NULL; + _mtp_packages = NULL; + } +} + +// Release module data resource. +ImageModuleData::~ImageModuleData() { + if (_data) { + delete _data; + } +} + +// Return the name of the module data resource. Ex. "./lib/modules/file.jimage" +// yields "file.jdata" +void ImageModuleData::module_data_name(char* buffer, const char* image_file_name) { + // Locate the last slash in the file name path. + const char* slash = strrchr(image_file_name, FileSeparator); + // Trim the path to name and extension. + const char* name = slash ? slash + 1 : (char *)image_file_name; + // Locate the extension period. + const char* dot = strrchr(name, '.'); + assert(dot && "missing extension on jimage name"); + // Trim to only base name. + int length = (int)(dot - name); + strncpy(buffer, name, length); + buffer[length] = '\0'; + // Append extension. + strcat(buffer, ".jdata"); +} + +// Return the module in which a package resides. Returns NULL if not found. +const char* ImageModuleData::package_to_module(const char* package_name) { + // Test files may contain no module data. + if (_data != NULL) { + // Search the package to module table. + s4 index = ImageStrings::find(_endian, package_name, _ptm_redirect, + _header->ptm_count(_endian)); + // If entry is found. + if (index != ImageStrings::NOT_FOUND) { + // Retrieve the package to module entry. + PTMData* data = _ptm_data + index; + // Verify that it is the correct data. + if (strcmp(package_name, get_string(data->name_offset(_endian))) != 0) { + return NULL; + } + // Return the module name. + return get_string(data->module_name_offset(_endian)); + } + } + return NULL; +} + +// Returns all the package names in a module in a NULL terminated array. +// Returns NULL if module not found. +const char** ImageModuleData::module_to_packages(const char* module_name) { + // Test files may contain no module data. + if (_data != NULL) { + // Search the module to package table. + s4 index = ImageStrings::find(_endian, module_name, _mtp_redirect, + _header->mtp_count(_endian)); + // If entry is found. + if (index != ImageStrings::NOT_FOUND) { + // Retrieve the module to package entry. + MTPData* data = _mtp_data + index; + // Verify that it is the correct data. + if (strcmp(module_name, get_string(data->name_offset(_endian))) != 0) { + return NULL; + } + // Construct an array of all the package entries. + u4 count = data->package_count(_endian); + const char** packages = new const char*[count + 1]; + s4 package_offset = data->package_offset(_endian); + for (u4 i = 0; i < count; i++) { + u4 package_name_offset = mtp_package(package_offset + i); + const char* package_name = get_string(package_name_offset); + packages[i] = package_name; + } + packages[count] = NULL; + return packages; + } + } + return NULL; +} + +// Manage a table of open image files. This table allows multiple access points +// to share an open image. +ImageFileReaderTable::ImageFileReaderTable() : _count(0), _max(_growth) { + _table = new ImageFileReader*[_max]; +} + +ImageFileReaderTable::~ImageFileReaderTable() { + delete _table; +} + +// Add a new image entry to the table. +void ImageFileReaderTable::add(ImageFileReader* image) { + if (_count == _max) { + _max += _growth; + _table = static_cast(realloc(_table, _max * sizeof(ImageFileReader*))); + } + _table[_count++] = image; +} + +// Remove an image entry from the table. +void ImageFileReaderTable::remove(ImageFileReader* image) { + s4 last = _count - 1; + for (s4 i = 0; _count; i++) { + if (_table[i] == image) { + if (i != last) { + _table[i] = _table[last]; + _count = last; + } + break; + } + } + + if (_count != 0 && _count == _max - _growth) { + _max -= _growth; + _table = static_cast(realloc(_table, _max * sizeof(ImageFileReader*))); + } +} + +// Determine if image entry is in table. +bool ImageFileReaderTable::contains(ImageFileReader* image) { + for (s4 i = 0; _count; i++) { + if (_table[i] == image) { + return true; + } + } + return false; +} + +// Table to manage multiple opens of an image file. +ImageFileReaderTable ImageFileReader::_reader_table; + +SimpleCriticalSection _reader_table_lock; + +// Open an image file, reuse structure if file already open. +ImageFileReader* ImageFileReader::open(const char* name, bool big_endian) { + { + // Lock out _reader_table. + SimpleCriticalSectionLock cs(&_reader_table_lock); + // Search for an exist image file. + for (u4 i = 0; i < _reader_table.count(); i++) { + // Retrieve table entry. + ImageFileReader* reader = _reader_table.get(i); + // If name matches, then reuse (bump up use count.) + if (strcmp(reader->name(), name) == 0) { + reader->inc_use(); + return reader; + } + } + } // Unlock the mutex + + // Need a new image reader. + ImageFileReader* reader = new ImageFileReader(name, big_endian); + bool opened = reader->open(); + // If failed to open. + if (!opened) { + delete reader; + return NULL; + } + + // Lock to update + SimpleCriticalSectionLock cs(&_reader_table_lock); + // Search for an exist image file. + for (u4 i = 0; i < _reader_table.count(); i++) { + // Retrieve table entry. + ImageFileReader* existing_reader = _reader_table.get(i); + // If name matches, then reuse (bump up use count.) + if (strcmp(existing_reader->name(), name) == 0) { + existing_reader->inc_use(); + reader->close(); + delete reader; + return existing_reader; + } + } + // Bump use count and add to table. + reader->inc_use(); + _reader_table.add(reader); + return reader; +} + +// Close an image file if the file is not in use elsewhere. +void ImageFileReader::close(ImageFileReader *reader) { + // Lock out _reader_table. + SimpleCriticalSectionLock cs(&_reader_table_lock); + // If last use then remove from table and then close. + if (reader->dec_use()) { + _reader_table.remove(reader); + delete reader; + } +} + +// Return an id for the specifed ImageFileReader. +u8 ImageFileReader::readerToID(ImageFileReader *reader) { + // ID is just the cloaked reader address. + return (u8)reader; +} + +// Validate the image id. +bool ImageFileReader::idCheck(u8 id) { + // Make sure the ID is a managed (_reader_table) reader. + SimpleCriticalSectionLock cs(&_reader_table_lock); + return _reader_table.contains((ImageFileReader*)id); +} + +// Return an id for the specifed ImageFileReader. +ImageFileReader* ImageFileReader::idToReader(u8 id) { + assert(idCheck(id) && "invalid image id"); + return (ImageFileReader*)id; +} + +// Constructor intializes to a closed state. +ImageFileReader::ImageFileReader(const char* name, bool big_endian) { + // Copy the image file name. + int len = (int) strlen(name) + 1; + _name = new char[len]; + strncpy(_name, name, len); + // Initialize for a closed file. + _fd = -1; + _endian = Endian::get_handler(big_endian); + _index_data = NULL; +} + +// Close image and free up data structures. +ImageFileReader::~ImageFileReader() { + // Ensure file is closed. + close(); + // Free up name. + if (_name) { + delete _name; + _name = NULL; + } +} + +// Open image file for read access. +bool ImageFileReader::open() { + char buffer[IMAGE_MAX_PATH]; + + // If file exists open for reading. + _fd = osSupport::openReadOnly(_name); + if (_fd == -1) { + return false; + } + // Retrieve the file size. + _file_size = osSupport::size(_name); + // Read image file header and verify it has a valid header. + size_t header_size = sizeof(ImageHeader); + if (_file_size < header_size || + !read_at((u1*)&_header, header_size, 0) || + _header.magic(_endian) != IMAGE_MAGIC || + _header.major_version(_endian) != MAJOR_VERSION || + _header.minor_version(_endian) != MINOR_VERSION) { + close(); + return false; + } + // Size of image index. + _index_size = index_size(); + // Make sure file is large enough to contain the index. + if (_file_size < _index_size) { + return false; + } + // Determine how much of the image is memory mapped. + size_t map_size = (size_t)(MemoryMapImage ? _file_size : _index_size); + // Memory map image (minimally the index.) + _index_data = (u1*)osSupport::map_memory(_fd, _name, 0, map_size); + assert(_index_data && "image file not memory mapped"); + // Retrieve length of index perfect hash table. + u4 length = table_length(); + // Compute offset of the perfect hash table redirect table. + u4 redirect_table_offset = (u4)header_size; + // Compute offset of index attribute offsets. + u4 offsets_table_offset = redirect_table_offset + length * sizeof(s4); + // Compute offset of index location attribute data. + u4 location_bytes_offset = offsets_table_offset + length * sizeof(u4); + // Compute offset of index string table. + u4 string_bytes_offset = location_bytes_offset + locations_size(); + // Compute address of the perfect hash table redirect table. + _redirect_table = (s4*)(_index_data + redirect_table_offset); + // Compute address of index attribute offsets. + _offsets_table = (u4*)(_index_data + offsets_table_offset); + // Compute address of index location attribute data. + _location_bytes = _index_data + location_bytes_offset; + // Compute address of index string table. + _string_bytes = _index_data + string_bytes_offset; + + // Initialize the module data + ImageModuleData::module_data_name(buffer, _name); + module_data = new ImageModuleData(this, buffer); + // Successful open. + return true; +} + +// Close image file. +void ImageFileReader::close() { + // Deallocate the index. + if (_index_data) { + osSupport::unmap_memory((char*)_index_data, _index_size); + _index_data = NULL; + } + // Close file. + if (_fd != -1) { + osSupport::close(_fd); + _fd = -1; + } +} + +// Read directly from the file. +bool ImageFileReader::read_at(u1* data, u8 size, u8 offset) const { + return (u8)osSupport::read(_fd, (char*)data, size, offset) == size; +} + +// Find the location attributes associated with the path. Returns true if +// the location is found, false otherwise. +bool ImageFileReader::find_location(const char* path, ImageLocation& location) const { + // Locate the entry in the index perfect hash table. + s4 index = ImageStrings::find(_endian, path, _redirect_table, table_length()); + // If is found. + if (index != ImageStrings::NOT_FOUND) { + // Get address of first byte of location attribute stream. + u1* data = get_location_data(index); + // Expand location attributes. + location.set_data(data); + // Make sure result is not a false positive. + return verify_location(location, path); + } + return false; +} + +// Find the location index and size associated with the path. +// Returns the location index and size if the location is found, 0 otherwise. +u4 ImageFileReader::find_location_index(const char* path, u8 *size) const { + // Locate the entry in the index perfect hash table. + s4 index = ImageStrings::find(_endian, path, _redirect_table, table_length()); + // If found. + if (index != ImageStrings::NOT_FOUND) { + // Get address of first byte of location attribute stream. + u4 offset = get_location_offset(index); + u1* data = get_location_offset_data(offset); + // Expand location attributes. + ImageLocation location(data); + // Make sure result is not a false positive. + if (verify_location(location, path)) { + *size = (jlong)location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED); + return offset; + } + } + return 0; // not found +} + +// Assemble the location path from the string fragments indicated in the location attributes. +void ImageFileReader::location_path(ImageLocation& location, char* path, size_t max) const { + // Manage the image string table. + ImageStrings strings(_string_bytes, _header.strings_size(_endian)); + // Position to first character of the path buffer. + char* next = path; + // Temp for string length. + size_t length; + // Get module string. + const char* module = location.get_attribute(ImageLocation::ATTRIBUTE_MODULE, strings); + // If module string is not empty string. + if (*module != '\0') { + // Get length of module name. + length = strlen(module); + // Make sure there is no buffer overflow. + assert(next - path + length + 2 < max && "buffer overflow"); + // Append '/module/'. + *next++ = '/'; + strncpy(next, module, length); next += length; + *next++ = '/'; + } + // Get parent (package) string. + const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings); + // If parent string is not empty string. + if (*parent != '\0') { + // Get length of module string. + length = strlen(parent); + // Make sure there is no buffer overflow. + assert(next - path + length + 1 < max && "buffer overflow"); + // Append 'patent/' . + strncpy(next, parent, length); next += length; + *next++ = '/'; + } + // Get base name string. + const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings); + // Get length of base name. + length = strlen(base); + // Make sure there is no buffer overflow. + assert(next - path + length < max && "buffer overflow"); + // Append base name. + strncpy(next, base, length); next += length; + // Get extension string. + const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings); + // If extension string is not empty string. + if (*extension != '\0') { + // Get length of extension string. + length = strlen(extension); + // Make sure there is no buffer overflow. + assert(next - path + length + 1 < max && "buffer overflow"); + // Append '.extension' . + *next++ = '.'; + strncpy(next, extension, length); next += length; + } + // Make sure there is no buffer overflow. + assert((size_t)(next - path) < max && "buffer overflow"); + // Terminate string. + *next = '\0'; +} + +// Verify that a found location matches the supplied path (without copying.) +bool ImageFileReader::verify_location(ImageLocation& location, const char* path) const { + // Manage the image string table. + ImageStrings strings(_string_bytes, _header.strings_size(_endian)); + // Position to first character of the path string. + const char* next = path; + // Get module name string. + const char* module = location.get_attribute(ImageLocation::ATTRIBUTE_MODULE, strings); + // If module string is not empty. + if (*module != '\0') { + // Compare '/module/' . + if (*next++ != '/') return false; + if (!(next = ImageStrings::starts_with(next, module))) return false; + if (*next++ != '/') return false; + } + // Get parent (package) string + const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings); + // If parent string is not empty string. + if (*parent != '\0') { + // Compare 'parent/' . + if (!(next = ImageStrings::starts_with(next, parent))) return false; + if (*next++ != '/') return false; + } + // Get base name string. + const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings); + // Compare with basne name. + if (!(next = ImageStrings::starts_with(next, base))) return false; + // Get extension string. + const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings); + // If extension is not empty. + if (*extension != '\0') { + // Compare '.extension' . + if (*next++ != '.') return false; + if (!(next = ImageStrings::starts_with(next, extension))) return false; + } + // True only if complete match and no more characters. + return *next == '\0'; +} + +// Return the resource for the supplied location offset. +void ImageFileReader::get_resource(u4 offset, u1* uncompressed_data) const { + // Get address of first byte of location attribute stream. + u1* data = get_location_offset_data(offset); + // Expand location attributes. + ImageLocation location(data); + // Read the data + get_resource(location, uncompressed_data); +} + +// Return the resource for the supplied location. +void ImageFileReader::get_resource(ImageLocation& location, u1* uncompressed_data) const { + // Retrieve the byte offset and size of the resource. + u8 offset = location.get_attribute(ImageLocation::ATTRIBUTE_OFFSET); + u8 uncompressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED); + u8 compressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_COMPRESSED); + // If the resource is compressed. + if (compressed_size != 0) { + u1* compressed_data; + // If not memory mapped read in bytes. + if (!MemoryMapImage) { + // Allocate buffer for compression. + compressed_data = new u1[(u4)compressed_size]; + // Read bytes from offset beyond the image index. + bool is_read = read_at(compressed_data, compressed_size, _index_size + offset); + assert(is_read && "error reading from image or short read"); + } else { + compressed_data = get_data_address() + offset; + } + // Get image string table. + const ImageStrings strings = get_strings(); + // Decompress resource. + ImageDecompressor::decompress_resource(compressed_data, uncompressed_data, (u4)uncompressed_size, + &strings); + // If not memory mapped then release temporary buffer. + if (!MemoryMapImage) { + delete compressed_data; + } + } else { + // Read bytes from offset beyond the image index. + bool is_read = read_at(uncompressed_data, uncompressed_size, _index_size + offset); + assert(is_read && "error reading from image or short read"); + } +} + +// Return the ImageModuleData for this image +ImageModuleData * ImageFileReader::get_image_module_data() { + return module_data; +} diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.base/share/native/libjimage/imageFile.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/native/libjimage/imageFile.hpp Thu Sep 10 14:55:20 2015 -0700 @@ -0,0 +1,648 @@ +/* + * 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. + * + */ + +#ifndef LIBJIMAGE_IMAGEFILE_HPP +#define LIBJIMAGE_IMAGEFILE_HPP + +#include + +#include "endian.hpp" +#include "inttypes.hpp" + +// Image files are an alternate file format for storing classes and resources. The +// goal is to supply file access which is faster and smaller than the jar format. +// It should be noted that unlike jars, information stored in an image is in native +// endian format. This allows the image to be mapped into memory without endian +// translation. This also means that images are platform dependent. +// +// Image files are structured as three sections; +// +// +-----------+ +// | Header | +// +-----------+ +// | | +// | Index | +// | | +// +-----------+ +// | | +// | | +// | Resources | +// | | +// | | +// +-----------+ +// +// The header contains information related to identification and description of +// contents. +// +// +-------------------------+ +// | Magic (0xCAFEDADA) | +// +------------+------------+ +// | Major Vers | Minor Vers | +// +------------+------------+ +// | Flags | +// +-------------------------+ +// | Resource Count | +// +-------------------------+ +// | Table Length | +// +-------------------------+ +// | Attributes Size | +// +-------------------------+ +// | Strings Size | +// +-------------------------+ +// +// Magic - means of identifying validity of the file. This avoids requiring a +// special file extension. +// Major vers, minor vers - differences in version numbers indicate structural +// changes in the image. +// Flags - various image wide flags (future). +// Resource count - number of resources in the file. +// Table length - the length of lookup tables used in the index. +// Attributes size - number of bytes in the region used to store location attribute +// streams. +// Strings size - the size of the region used to store strings used by the +// index and meta data. +// +// The index contains information related to resource lookup. The algorithm +// used for lookup is "A Practical Minimal Perfect Hashing Method" +// (http://homepages.dcc.ufmg.br/~nivio/papers/wea05.pdf). Given a path string +// in the form ///. return the resource location +// information; +// +// redirectIndex = hash(path, DEFAULT_SEED) % table_length; +// redirect = redirectTable[redirectIndex]; +// if (redirect == 0) return not found; +// locationIndex = redirect < 0 ? -1 - redirect : hash(path, redirect) % table_length; +// location = locationTable[locationIndex]; +// if (!verify(location, path)) return not found; +// return location; +// +// Note: The hash function takes an initial seed value. A different seed value +// usually returns a different result for strings that would otherwise collide with +// other seeds. The verify function guarantees the found resource location is +// indeed the resource we are looking for. +// +// The following is the format of the index; +// +// +-------------------+ +// | Redirect Table | +// +-------------------+ +// | Attribute Offsets | +// +-------------------+ +// | Attribute Data | +// +-------------------+ +// | Strings | +// +-------------------+ +// +// Redirect Table - Array of 32-bit signed values representing actions that +// should take place for hashed strings that map to that +// value. Negative values indicate no hash collision and can be +// quickly converted to indices into attribute offsets. Positive +// values represent a new seed for hashing an index into attribute +// offsets. Zero indicates not found. +// Attribute Offsets - Array of 32-bit unsigned values representing offsets into +// attribute data. Attribute offsets can be iterated to do a +// full survey of resources in the image. Offset of zero +// indicates no attributes. +// Attribute Data - Bytes representing compact attribute data for locations. (See +// comments in ImageLocation.) +// Strings - Collection of zero terminated UTF-8 strings used by the index and +// image meta data. Each string is accessed by offset. Each string is +// unique. Offset zero is reserved for the empty string. +// +// Note that the memory mapped index assumes 32 bit alignment of each component +// in the index. +// +// Endianness of an image. +// An image booted by hotspot is always in native endian. However, it is possible +// to read (by the JDK) in alternate endian format. Primarily, this is during +// cross platform scenarios. Ex, where javac needs to read an embedded image +// to access classes for crossing compilation. +// + +class ImageFileReader; // forward declaration + +// Manage image file string table. +class ImageStrings { +private: + u1* _data; // Data bytes for strings. + u4 _size; // Number of bytes in the string table. +public: + enum { + // Not found result from find routine. + NOT_FOUND = -1, + // Prime used to generate hash for Perfect Hashing. + HASH_MULTIPLIER = 0x01000193 + }; + + ImageStrings(u1* data, u4 size) : _data(data), _size(size) {} + + // Return the UTF-8 string beginning at offset. + inline const char* get(u4 offset) const { + assert(offset < _size && "offset exceeds string table size"); + return (const char*)(_data + offset); + } + + // Compute the Perfect Hashing hash code for the supplied UTF-8 string. + inline static u4 hash_code(const char* string) { + return hash_code(string, HASH_MULTIPLIER); + } + + // Compute the Perfect Hashing hash code for the supplied string, starting at seed. + static s4 hash_code(const char* string, s4 seed); + + // Match up a string in a perfect hash table. Result still needs validation + // for precise match. + static s4 find(Endian* endian, const char* name, s4* redirect, u4 length); + + // Test to see if UTF-8 string begins with the start UTF-8 string. If so, + // return non-NULL address of remaining portion of string. Otherwise, return + // NULL. Used to test sections of a path without copying from image string + // table. + static const char* starts_with(const char* string, const char* start); + + // Test to see if UTF-8 string begins with start char. If so, return non-NULL + // address of remaining portion of string. Otherwise, return NULL. Used + // to test a character of a path without copying. + inline static const char* starts_with(const char* string, const char ch) { + return *string == ch ? string + 1 : NULL; + } +}; + +// Manage image file location attribute data. Within an image, a location's +// attributes are compressed into a stream of bytes. An attribute stream is +// composed of individual attribute sequences. Each attribute sequence begins with +// a header byte containing the attribute 'kind' (upper 5 bits of header) and the +// 'length' less 1 (lower 3 bits of header) of bytes that follow containing the +// attribute value. Attribute values present as most significant byte first. +// +// Ex. Container offset (ATTRIBUTE_OFFSET) 0x33562 would be represented as 0x22 +// (kind = 4, length = 3), 0x03, 0x35, 0x62. +// +// An attribute stream is terminated with a header kind of ATTRIBUTE_END (header +// byte of zero.) +// +// ImageLocation inflates the stream into individual values stored in the long +// array _attributes. This allows an attribute value can be quickly accessed by +// direct indexing. Unspecified values default to zero. +// +// Notes: +// - Even though ATTRIBUTE_END is used to mark the end of the attribute stream, +// streams will contain zero byte values to represent lesser significant bits. +// Thus, detecting a zero byte is not sufficient to detect the end of an attribute +// stream. +// - ATTRIBUTE_OFFSET represents the number of bytes from the beginning of the region +// storing the resources. Thus, in an image this represents the number of bytes +// after the index. +// - Currently, compressed resources are represented by having a non-zero +// ATTRIBUTE_COMPRESSED value. This represents the number of bytes stored in the +// image, and the value of ATTRIBUTE_UNCOMPRESSED represents number of bytes of the +// inflated resource in memory. If the ATTRIBUTE_COMPRESSED is zero then the value +// of ATTRIBUTE_UNCOMPRESSED represents both the number of bytes in the image and +// in memory. In the future, additional compression techniques will be used and +// represented differently. +// - Package strings include trailing slash and extensions include prefix period. +// +class ImageLocation { +public: + enum { + ATTRIBUTE_END, // End of attribute stream marker + ATTRIBUTE_MODULE, // String table offset of module name + ATTRIBUTE_PARENT, // String table offset of resource path parent + ATTRIBUTE_BASE, // String table offset of resource path base + ATTRIBUTE_EXTENSION, // String table offset of resource path extension + ATTRIBUTE_OFFSET, // Container byte offset of resource + ATTRIBUTE_COMPRESSED, // In image byte size of the compressed resource + ATTRIBUTE_UNCOMPRESSED, // In memory byte size of the uncompressed resource + ATTRIBUTE_COUNT // Number of attribute kinds + }; + +private: + // Values of inflated attributes. + u8 _attributes[ATTRIBUTE_COUNT]; + + // Return the attribute value number of bytes. + inline static u1 attribute_length(u1 data) { + return (data & 0x7) + 1; + } + + // Return the attribute kind. + inline static u1 attribute_kind(u1 data) { + u1 kind = data >> 3; + assert(kind < ATTRIBUTE_COUNT && "invalid attribute kind"); + return kind; + } + + // Return the attribute length. + inline static u8 attribute_value(u1* data, u1 n) { + assert(0 < n && n <= 8 && "invalid attribute value length"); + u8 value = 0; + // Most significant bytes first. + for (u1 i = 0; i < n; i++) { + value <<= 8; + value |= data[i]; + } + return value; + } + +public: + ImageLocation() { + clear_data(); + } + + ImageLocation(u1* data) { + clear_data(); + set_data(data); + } + + // Inflates the attribute stream into individual values stored in the long + // array _attributes. This allows an attribute value to be quickly accessed by + // direct indexing. Unspecified values default to zero. + void set_data(u1* data); + + // Zero all attribute values. + void clear_data(); + + // Retrieve an attribute value from the inflated array. + inline u8 get_attribute(u1 kind) const { + assert(ATTRIBUTE_END < kind && kind < ATTRIBUTE_COUNT && "invalid attribute kind"); + return _attributes[kind]; + } + + // Retrieve an attribute string value from the inflated array. + inline const char* get_attribute(u4 kind, const ImageStrings& strings) const { + return strings.get((u4)get_attribute(kind)); + } +}; + +// +// NOTE: needs revision. +// Each loader requires set of module meta data to identify which modules and +// packages are managed by that loader. Currently, there is one image file per +// builtin loader, so only one module meta data resource per file. +// +// Each element in the module meta data is a native endian 4 byte integer. Note +// that entries with zero offsets for string table entries should be ignored ( +// padding for hash table lookup.) +// +// Format: +// Count of package to module entries +// Count of module to package entries +// Perfect Hash redirect table[Count of package to module entries] +// Package to module entries[Count of package to module entries] +// Offset to package name in string table +// Offset to module name in string table +// Perfect Hash redirect table[Count of module to package entries] +// Module to package entries[Count of module to package entries] +// Offset to module name in string table +// Count of packages in module +// Offset to first package in packages table +// Packages[] +// Offset to package name in string table +// +// Manage the image module meta data. +class ImageModuleData { + class Header { + private: + u4 _ptm_count; // Count of package to module entries + u4 _mtp_count; // Count of module to package entries + public: + inline u4 ptm_count(Endian* endian) const { return endian->get(_ptm_count); } + inline u4 mtp_count(Endian* endian) const { return endian->get(_mtp_count); } + }; + + // Hashtable entry + class HashData { + private: + u4 _name_offset; // Name offset in string table + public: + inline s4 name_offset(Endian* endian) const { return endian->get(_name_offset); } + }; + + // Package to module hashtable entry + class PTMData : public HashData { + private: + u4 _module_name_offset; // Module name offset in string table + public: + inline s4 module_name_offset(Endian* endian) const { return endian->get(_module_name_offset); } + }; + + // Module to package hashtable entry + class MTPData : public HashData { + private: + u4 _package_count; // Number of packages in module + u4 _package_offset; // Offset in package list + public: + inline u4 package_count(Endian* endian) const { return endian->get(_package_count); } + inline u4 package_offset(Endian* endian) const { return endian->get(_package_offset); } + }; + + const ImageFileReader* _image_file; // Source image file + Endian* _endian; // Endian handler + ImageStrings _strings; // Image file strings + u1* _data; // Module data resource data + u8 _data_size; // Size of resource data + Header* _header; // Module data header + s4* _ptm_redirect; // Package to module hashtable redirect + PTMData* _ptm_data; // Package to module data + s4* _mtp_redirect; // Module to packages hashtable redirect + MTPData* _mtp_data; // Module to packages data + s4* _mtp_packages; // Package data (name offsets) + + // Return a string from the string table. + inline const char* get_string(u4 offset) { + return _strings.get(offset); + } + + inline u4 mtp_package(u4 index) { + return _endian->get(_mtp_packages[index]); + } + +public: + ImageModuleData(const ImageFileReader* image_file, const char* module_data_name); + ~ImageModuleData(); + + // Return the name of the module data resource. + static void module_data_name(char* buffer, const char* image_file_name); + + // Return the module in which a package resides. Returns NULL if not found. + const char* package_to_module(const char* package_name); + + // Returns all the package names in a module in a NULL terminated array. + // Returns NULL if module not found. + const char** module_to_packages(const char* module_name); +}; + +// Image file header, starting at offset 0. +class ImageHeader { +private: + u4 _magic; // Image file marker + u4 _version; // Image file major version number + u4 _flags; // Image file flags + u4 _resource_count; // Number of resources in file + u4 _table_length; // Number of slots in index tables + u4 _locations_size; // Number of bytes in attribute table + u4 _strings_size; // Number of bytes in string table + +public: + u4 magic() const { return _magic; } + u4 magic(Endian* endian) const { return endian->get(_magic); } + void set_magic(Endian* endian, u4 magic) { return endian->set(_magic, magic); } + + u4 major_version(Endian* endian) const { return endian->get(_version) >> 16; } + u4 minor_version(Endian* endian) const { return endian->get(_version) & 0xFFFF; } + void set_version(Endian* endian, u4 major_version, u4 minor_version) { + return endian->set(_version, major_version << 16 | minor_version); + } + + u4 flags(Endian* endian) const { return endian->get(_flags); } + void set_flags(Endian* endian, u4 value) { return endian->set(_flags, value); } + + u4 resource_count(Endian* endian) const { return endian->get(_resource_count); } + void set_resource_count(Endian* endian, u4 count) { return endian->set(_resource_count, count); } + + u4 table_length(Endian* endian) const { return endian->get(_table_length); } + void set_table_length(Endian* endian, u4 count) { return endian->set(_table_length, count); } + + u4 locations_size(Endian* endian) const { return endian->get(_locations_size); } + void set_locations_size(Endian* endian, u4 size) { return endian->set(_locations_size, size); } + + u4 strings_size(Endian* endian) const { return endian->get(_strings_size); } + void set_strings_size(Endian* endian, u4 size) { return endian->set(_strings_size, size); } +}; + +// Max path length limit independent of platform. Windows max path is 1024, +// other platforms use 4096. The JCK fails several tests when 1024 is used. +#define IMAGE_MAX_PATH 4096 + +class ImageFileReader; + +// Manage a table of open image files. This table allows multiple access points +// to share an open image. +class ImageFileReaderTable { +private: + const static u4 _growth = 8; // Growth rate of the table + u4 _count; // Number of entries in the table + u4 _max; // Maximum number of entries allocated + ImageFileReader** _table; // Growable array of entries + +public: + ImageFileReaderTable(); + ~ImageFileReaderTable(); + + // Return the number of entries. + inline u4 count() { return _count; } + + // Return the ith entry from the table. + inline ImageFileReader* get(u4 i) { return _table[i]; } + + // Add a new image entry to the table. + void add(ImageFileReader* image); + + // Remove an image entry from the table. + void remove(ImageFileReader* image); + + // Determine if image entry is in table. + bool contains(ImageFileReader* image); +}; + +// Manage the image file. +// ImageFileReader manages the content of an image file. +// Initially, the header of the image file is read for validation. If valid, +// values in the header are used calculate the size of the image index. The +// index is then memory mapped to allow load on demand and sharing. The +// -XX:+MemoryMapImage flag determines if the entire file is loaded (server use.) +// An image can be used by Hotspot and multiple reference points in the JDK, thus +// it is desirable to share a reader. To accomodate sharing, a share table is +// defined (see ImageFileReaderTable in imageFile.cpp) To track the number of +// uses, ImageFileReader keeps a use count (_use). Use is incremented when +// 'opened' by reference point and decremented when 'closed'. Use of zero +// leads the ImageFileReader to be actually closed and discarded. +class ImageFileReader { +private: + // Manage a number of image files such that an image can be shared across + // multiple uses (ex. loader.) + static ImageFileReaderTable _reader_table; + + char* _name; // Name of image + s4 _use; // Use count + int _fd; // File descriptor + Endian* _endian; // Endian handler + u8 _file_size; // File size in bytes + ImageHeader _header; // Image header + size_t _index_size; // Total size of index + u1* _index_data; // Raw index data + s4* _redirect_table; // Perfect hash redirect table + u4* _offsets_table; // Location offset table + u1* _location_bytes; // Location attributes + u1* _string_bytes; // String table + ImageModuleData *module_data; // The ImageModuleData for this image + + ImageFileReader(const char* name, bool big_endian); + ~ImageFileReader(); + + // Compute number of bytes in image file index. + inline size_t index_size() { + return sizeof(ImageHeader) + + table_length() * sizeof(u4) * 2 + locations_size() + strings_size(); + } + +public: + enum { + // Image file marker. + IMAGE_MAGIC = 0xCAFEDADA, + // Endian inverted Image file marker. + IMAGE_MAGIC_INVERT = 0xDADAFECA, + // Image file major version number. + MAJOR_VERSION = 1, + // Image file minor version number. + MINOR_VERSION = 0 + }; + + // Open an image file, reuse structure if file already open. + static ImageFileReader* open(const char* name, bool big_endian = Endian::is_big_endian()); + + // Close an image file if the file is not in use elsewhere. + static void close(ImageFileReader *reader); + + // Return an id for the specifed ImageFileReader. + static u8 readerToID(ImageFileReader *reader); + + // Validate the image id. + static bool idCheck(u8 id); + + // Return an id for the specifed ImageFileReader. + static ImageFileReader* idToReader(u8 id); + + // Open image file for read access. + bool open(); + + // Close image file. + void close(); + + // Read directly from the file. + bool read_at(u1* data, u8 size, u8 offset) const; + + inline Endian* endian() const { return _endian; } + + // Retrieve name of image file. + inline const char* name() const { + return _name; + } + + // Retrieve size of image file. + inline u8 file_size() const { + return _file_size; + } + + // Return first address of index data. + inline u1* get_index_address() const { + return _index_data; + } + + // Return first address of resource data. + inline u1* get_data_address() const { + return _index_data + _index_size; + } + + // Get the size of the index data. + size_t get_index_size() const { + return _index_size; + } + + inline u4 table_length() const { + return _header.table_length(_endian); + } + + inline u4 locations_size() const { + return _header.locations_size(_endian); + } + + inline u4 strings_size()const { + return _header.strings_size(_endian); + } + + inline u4* offsets_table() const { + return _offsets_table; + } + + // Increment use count. + inline void inc_use() { + _use++; + } + + // Decrement use count. + inline bool dec_use() { + return --_use == 0; + } + + // Return a string table accessor. + inline const ImageStrings get_strings() const { + return ImageStrings(_string_bytes, _header.strings_size(_endian)); + } + + // Return location attribute stream at offset. + inline u1* get_location_offset_data(u4 offset) const { + assert((u4)offset < _header.locations_size(_endian) && + "offset exceeds location attributes size"); + return offset != 0 ? _location_bytes + offset : NULL; + } + + // Return location attribute stream for location i. + inline u1* get_location_data(u4 index) const { + return get_location_offset_data(get_location_offset(index)); + } + + // Return the location offset for index. + inline u4 get_location_offset(u4 index) const { + assert((u4)index < _header.table_length(_endian) && + "index exceeds location count"); + return _endian->get(_offsets_table[index]); + } + + // Find the location attributes associated with the path. Returns true if + // the location is found, false otherwise. + bool find_location(const char* path, ImageLocation& location) const; + + // Find the location index and size associated with the path. + // Returns the location index and size if the location is found, + // ImageFileReader::NOT_FOUND otherwise. + u4 find_location_index(const char* path, u8 *size) const; + + // Assemble the location path. + void location_path(ImageLocation& location, char* path, size_t max) const; + + // Verify that a found location matches the supplied path. + bool verify_location(ImageLocation& location, const char* path) const; + + // Return the resource for the supplied location index. + void get_resource(u4 index, u1* uncompressed_data) const; + + // Return the resource for the supplied path. + void get_resource(ImageLocation& location, u1* uncompressed_data) const; + + // Return the ImageModuleData for this image + ImageModuleData * get_image_module_data(); + +}; +#endif // LIBJIMAGE_IMAGEFILE_HPP diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.base/share/native/libjimage/inttypes.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/native/libjimage/inttypes.hpp Thu Sep 10 14:55:20 2015 -0700 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015, 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. + * + */ + +#ifndef LIBJIMAGE_INTTYPES_HPP +#define LIBJIMAGE_INTTYPES_HPP + +typedef unsigned char u1; +typedef char s1; +typedef unsigned short u2; +typedef short s2; +typedef unsigned int u4; +typedef int s4; +#ifdef LP64 +typedef unsigned long u8; +typedef long s8; +#else +typedef unsigned long long u8; +typedef long long s8; +#endif + +#endif // LIBJIMAGE_INTTYPES_HPP + diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.base/share/native/libjimage/jimage.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/native/libjimage/jimage.cpp Thu Sep 10 14:55:20 2015 -0700 @@ -0,0 +1,194 @@ +/* + * 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. + * + */ + +#include + +#include "jimage.hpp" + +#include "imageFile.hpp" + +#define BOOT_VERSION "9.0" + +/* + * JImageOpen - Given the supplied full path file name, open an image file. This + * function will also initialize tables and retrieve meta-data necessary to + * satisfy other functions in the API. If the image file has been previously + * open, a new open request will share memory and resources used by the previous + * open. A call to JImageOpen should be balanced by a call to JImageClose, to + * release memory and resources used. If the image file is not found or cannot + * be open, then NULL is returned and error will contain a reason for the + * failure; a positive value for a system error number, negative for a jimage + * specific error (see JImage Error Codes.) + * + * Ex. + * jint error; + * JImageFile* jimage = (*JImageOpen)(JAVA_HOME "lib/modules/bootmodules.jimage", &error); + * if (image == NULL) { + * tty->print_cr("JImage failed to open: %d", error); + * ... + * } + * ... + */ +extern "C" JImageFile* JIMAGE_Open(const char *name, jint* error) { + // TODO - return a meaningful error code + *error = 0; + ImageFileReader* jfile = ImageFileReader::open(name); + return (JImageFile*) jfile; +} + +/* + * JImageClose - Given the supplied open image file (see JImageOpen), release + * memory and resources used by the open file and close the file. If the image + * file is shared by other uses, release and close is deferred until the last use + * is also closed. + * + * Ex. + * (*JImageClose)(image); + */ +extern "C" void JIMAGE_Close(JImageFile* image) { + ImageFileReader::close((ImageFileReader*) image); +} + +/* + * JImagePackageToModule - Given an open image file (see JImageOpen) and the name + * of a package, return the name of module where the package resides. If the + * package does not exist in the image file, the function returns NULL. + * The resulting string does/should not have to be released. All strings are + * utf-8, zero byte terminated. + * + * Ex. + * const char* package = (*JImagePackageToModule)(image, "java/lang"); + * tty->print_cr(package); + * —> java.base + */ +extern "C" const char* JIMAGE_PackageToModule(JImageFile* image, const char* package_name) { + return ((ImageFileReader*) image)->get_image_module_data()->package_to_module(package_name); +} + +/* + * JImageFindResource - Given an open image file (see JImageOpen), a module + * name, a version string and the name of a class/resource, return location + * information describing the resource and its size. If no resource is found, the + * function returns JIMAGE_NOT_FOUND and the value of size is undefined. + * The version number should be "9.0" and is not used in locating the resource. + * The resulting location does/should not have to be released. + * All strings are utf-8, zero byte terminated. + * + * Ex. + * jlong size; + * JImageLocationRef location = (*JImageFindResource)(image, "java.base", "9.0", "java/lang/String.class", &size); + */ +extern "C" JImageLocationRef JIMAGE_FindResource(JImageFile* image, + const char* module_name, const char* version, const char* name, + jlong* size) { + if (strcmp(version, BOOT_VERSION) != 0) { + return (JImageLocationRef) 0; + } + + ImageLocation location; + char fullpath[IMAGE_MAX_PATH]; + + // Concatenate to get full path + strncpy(fullpath, "/", IMAGE_MAX_PATH - 1); + strncat(fullpath, module_name, IMAGE_MAX_PATH - 1); + strncat(fullpath, "/", IMAGE_MAX_PATH - 1); + strncat(fullpath, name, IMAGE_MAX_PATH - 1); + JImageLocationRef loc = + (JImageLocationRef) ((ImageFileReader*) image)->find_location_index(fullpath, (u8*) size); + return loc; +} + +/* + * JImageGetResource - Given an open image file (see JImageOpen), a resource’s + * location information (see JImageFindResource), a buffer of appropriate + * size and the size, retrieve the bytes associated with the + * resource. If the size is less than the resource size then the read is truncated. + * If the size is greater than the resource size then the remainder of the buffer + * is zero filled. The function will return the actual size of the resource. + * + * Ex. + * jlong size; + * JImageLocationRef* location = (*JImageFindResource)(image, "java.base", "9.0", "java/lang/String.class", &size); + * char* buffer = new char[size]; + * (*JImageGetResource)(image, location, buffer, size); + */ +extern "C" jlong JIMAGE_GetResource(JImageFile* image, JImageLocationRef location, + char* buffer, jlong size) { + ((ImageFileReader*) image)->get_resource((u4) location, (u1*) buffer); + return size; +} + +/* + * JImageResourceIterator - Given an open image file (see JImageOpen), a visitor + * function and a visitor argument, iterator through each of the image's resources. + * The visitor function is called with the image file, the module name, the + * package name, the base name, the extension and the visitor argument. The return + * value of the visitor function should be true, unless an early iteration exit is + * required. All strings are utf-8, zero byte terminated.file. + * + * Ex. + * bool ctw_visitor(JImageFile* jimage, const char* module_name, const char* version, const char* package, const char* name, const char* extension, void* arg) { + * if (strcmp(extension, “class”) == 0) { + * char path[JIMAGE_MAX_PATH]; + * Thread* THREAD = Thread::current(); + * jio_snprintf(path, JIMAGE_MAX_PATH - 1, "/%s/%s", package, name); + * ClassLoader::compile_the_world_in(path, (Handle)arg, THREAD); + * return !HAS_PENDING_EXCEPTION; + * } + * return true; + * } + * (*JImageResourceIterator)(image, ctw_visitor, loader); + */ +extern "C" void JIMAGE_ResourceIterator(JImageFile* image, + JImageResourceVisitor_t visitor, void* arg) { + ImageFileReader* imageFile = (ImageFileReader*) image; + u4 nEntries = imageFile->table_length(); + const ImageStrings strings = imageFile->get_strings(); + for (u4 i = 0; i < nEntries; i++) { + ImageLocation location(imageFile->get_location_data(i)); + + u4 moduleOffset = (u4) location.get_attribute(ImageLocation::ATTRIBUTE_MODULE); + if (moduleOffset == 0) { + continue; // skip non-modules + } + const char *module = strings.get(moduleOffset); + if (strcmp(module, "modules") == 0 + || strcmp(module, "packages") == 0) { + continue; // always skip + } + + u4 parentOffset = (u4) location.get_attribute(ImageLocation::ATTRIBUTE_PARENT); + const char *parent = strings.get(parentOffset); + u4 baseOffset = (u4) location.get_attribute(ImageLocation::ATTRIBUTE_BASE); + const char *base = strings.get(baseOffset); + u4 extOffset = (u4) location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION); + const char *extension = strings.get(extOffset); + + if (!(*visitor)(image, module, "9", parent, base, extension, arg)) { + break; + } + + } +} + diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.base/share/native/libjimage/jimage.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/native/libjimage/jimage.hpp Thu Sep 10 14:55:20 2015 -0700 @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2015, 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" + +// Opaque reference to a JImage file. +class JImageFile; +// Opaque reference to an image file resource location. +typedef jlong JImageLocationRef; + +// Max path length limit independent of platform. Windows max path is 1024, +// other platforms use 4096. The JCK fails several tests when 1024 is used. +#define JIMAGE_MAX_PATH 4096 + +// JImage Error Codes + +// The image file is not prefixed with 0xCAFEDADA +#define JIMAGE_BAD_MAGIC (-1) +// The image file does not have a compatible (translatable) version +#define JIMAGE_BAD_VERSION (-2) +// The image file content is malformed +#define JIMAGE_CORRUPTED (-3) + +/* + * JImageOpen - Given the supplied full path file name, open an image file. This + * function will also initialize tables and retrieve meta-data necessary to + * satisfy other functions in the API. If the image file has been previously + * open, a new open request will share memory and resources used by the previous + * open. A call to JImageOpen should be balanced by a call to JImageClose, to + * release memory and resources used. If the image file is not found or cannot + * be open, then NULL is returned and error will contain a reason for the + * failure; a positive value for a system error number, negative for a jimage + * specific error (see JImage Error Codes.) + * + * Ex. + * jint error; + * JImageFile* jimage = (*JImageOpen)(JAVA_HOME "lib/modules/bootmodules.jimage", &error); + * if (image == NULL) { + * tty->print_cr("JImage failed to open: %d", error); + * ... + * } + * ... + */ + +extern "C" JImageFile* JIMAGE_Open(const char *name, jint* error); + +typedef JImageFile* (*JImageOpen_t)(const char *name, jint* error); + +/* + * JImageClose - Given the supplied open image file (see JImageOpen), release + * memory and resources used by the open file and close the file. If the image + * file is shared by other uses, release and close is deferred until the last use + * is also closed. + * + * Ex. + * (*JImageClose)(image); + */ + +extern "C" void JIMAGE_Close(JImageFile* jimage); + +typedef void (*JImageClose_t)(JImageFile* jimage); + + +/* + * JImagePackageToModule - Given an open image file (see JImageOpen) and the name + * of a package, return the name of module where the package resides. If the + * package does not exist in the image file, the function returns NULL. + * The resulting string does/should not have to be released. All strings are + * utf-8, zero byte terminated. + * + * Ex. + * const char* package = (*JImagePackageToModule)(image, "java/lang"); + * tty->print_cr(package); + * —> java.base + */ + +extern "C" const char * JIMAGE_PackageToModule(JImageFile* jimage, const char* package_name); + +typedef const char* (*JImagePackageToModule_t)(JImageFile* jimage, const char* package_name); + + +/* + * JImageFindResource - Given an open image file (see JImageOpen), a module + * name, a version string and the name of a class/resource, return location + * information describing the resource and its size. If no resource is found, the + * function returns JIMAGE_NOT_FOUND and the value of size is undefined. + * The version number should be "9.0" and is not used in locating the resource. + * The resulting location does/should not have to be released. + * All strings are utf-8, zero byte terminated. + * + * Ex. + * jlong size; + * JImageLocationRef location = (*JImageFindResource)(image, "java.base", "9.0", "java/lang/String.class", &size); + */ +extern "C" JImageLocationRef JIMAGE_FindResource(JImageFile* jimage, + const char* module_name, const char* version, const char* name, + jlong* size); + +typedef JImageLocationRef(*JImageFindResource_t)(JImageFile* jimage, + const char* module_name, const char* version, const char* name, + jlong* size); + + +/* + * JImageGetResource - Given an open image file (see JImageOpen), a resource’s + * location information (see JImageFindResource), a buffer of appropriate + * size and the size, retrieve the bytes associated with the + * resource. If the size is less than the resource size then the read is truncated. + * If the size is greater than the resource size then the remainder of the buffer + * is zero filled. The function will return the actual size of the resource. + * + * Ex. + * jlong size; + * JImageLocationRef location = (*JImageFindResource)(image, "java.base", "9.0", "java/lang/String.class", &size); + * char* buffer = new char[size]; + * (*JImageGetResource)(image, location, buffer, size); + */ +extern "C" jlong JIMAGE_GetResource(JImageFile* jimage, JImageLocationRef location, + char* buffer, jlong size); + +typedef jlong(*JImageGetResource_t)(JImageFile* jimage, JImageLocationRef location, + char* buffer, jlong size); + + +/* + * JImageResourceIterator - Given an open image file (see JImageOpen), a visitor + * function and a visitor argument, iterator through each of the image's resources. + * The visitor function is called with the image file, the module name, the + * package name, the base name, the extension and the visitor argument. The return + * value of the visitor function should be true, unless an early iteration exit is + * required. All strings are utf-8, zero byte terminated.file. + * + * Ex. + * bool ctw_visitor(JImageFile* jimage, const char* module_name, const char* version, const char* package, const char* name, const char* extension, void* arg) { + * if (strcmp(extension, “class”) == 0) { + * char path[JIMAGE_MAX_PATH]; + * Thread* THREAD = Thread::current(); + * jio_snprintf(path, JIMAGE_MAX_PATH - 1, "/%s/%s", package, name); + * ClassLoader::compile_the_world_in(path, (Handle)arg, THREAD); + * return !HAS_PENDING_EXCEPTION; + * } + * return true; + * } + * (*JImageResourceIterator)(image, ctw_visitor, loader); + */ + +typedef bool (*JImageResourceVisitor_t)(JImageFile* jimage, + const char* module_name, const char* version, const char* package, + const char* name, const char* extension, void* arg); + +extern "C" void JIMAGE_ResourceIterator(JImageFile* jimage, + JImageResourceVisitor_t visitor, void *arg); + +typedef void (*JImageResourceIterator_t)(JImageFile* jimage, + JImageResourceVisitor_t visitor, void* arg); diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.base/share/native/libjimage/osSupport.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/native/libjimage/osSupport.hpp Thu Sep 10 14:55:20 2015 -0700 @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2015, 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. + * + */ + +#ifndef LIBJIMAGE_OSSUPPORT_HPP +#define LIBJIMAGE_OSSUPPORT_HPP + +#ifdef WIN32 +#include +#else +#include +#endif + +class osSupport { +public: + /** + * Open a regular file read-only. + * Return the file descriptor. + */ + static jint openReadOnly(const char *path); + + /** + * Close a file descriptor. + */ + static jint close(jint fd); + + /** + * Return the size of a regular file. + */ + static jlong size(const char *path); + + /** + * Read nBytes at offset into a buffer. + */ + static jlong read(jint fd, char *buf, jlong nBytes, jlong offset); + + /** + * Map nBytes at offset into memory and return the address. + * The system chooses the address. + */ + static void* map_memory(jint fd, const char *filename, size_t file_offset, size_t bytes); + + /** + * Unmap nBytes of memory at address. + */ + static int unmap_memory(void* addr, size_t bytes); +}; + +/** + * A CriticalSection to protect a small section of code. + */ +class SimpleCriticalSection { + friend class SimpleCriticalSectionLock; +private: + void enter(); + void exit(); +public: + SimpleCriticalSection(); + //~SimpleCriticalSection(); // Cretes a dependency on Solaris on a C++ exit registration + +private: +#ifdef WIN32 + CRITICAL_SECTION critical_section; +#else + pthread_mutex_t mutex; +#endif // WIN32 +}; + +/** + * SimpleCriticalSectionLock instance. + * The constructor locks a SimpleCriticalSection and the + * destructor does the unlock. + */ +class SimpleCriticalSectionLock { +private: + SimpleCriticalSection *lock; +public: + + SimpleCriticalSectionLock(SimpleCriticalSection *cslock) { + this->lock = cslock; + lock->enter(); + } + + ~SimpleCriticalSectionLock() { + lock->exit(); + } +}; + +#endif // LIBJIMAGE_OSSUPPORT_HPP diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.base/unix/native/libjimage/osSupport_unix.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/unix/native/libjimage/osSupport_unix.cpp Thu Sep 10 14:55:20 2015 -0700 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015, 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 +#include +#include +#include +#include +#include + +#include "jni.h" +#include "osSupport.hpp" + +/** + * Open a regular file read-only. + * Return the file descriptor. + */ +jint osSupport::openReadOnly(const char *path) { + return ::open(path, 0); +} + +/** + * Close a file descriptor. + */ +jint osSupport::close(jint fd) { + return ::close(fd); +} + +/** + * Return the size of a regular file. + */ +jlong osSupport::size(const char *path) { + struct stat statbuf; + if (stat(path, &statbuf) < 0 || + (statbuf.st_mode & S_IFREG) != S_IFREG) { + return -1; + } + return (jsize) statbuf.st_size; +} + +/** + * Read nBytes at offset into a buffer. + */ +jlong osSupport::read(jint fd, char *buf, jlong nBytes, jlong offset) { + return ::pread(fd, buf, nBytes, offset); +} + +/** + * Map nBytes at offset into memory and return the address. + * The system chooses the address. + */ +void* osSupport::map_memory(int fd, const char *filename, size_t file_offset, size_t bytes) { + void* mapped_address = NULL; + mapped_address = (void*) mmap(NULL, + bytes, PROT_READ, MAP_SHARED, + fd, file_offset); + if (mapped_address == MAP_FAILED) { + return NULL; + } + return mapped_address; +} + +/** + * Unmap nBytes of memory at address. + */ +int osSupport::unmap_memory(void *addr, size_t bytes) { + return munmap((char *) addr, bytes) == 0; +} + +/** + * A CriticalSection to protect a small section of code. + */ +void SimpleCriticalSection::enter() { + pthread_mutex_lock(&mutex); +} + +void SimpleCriticalSection::exit() { + pthread_mutex_unlock(&mutex); + +} + +SimpleCriticalSection::SimpleCriticalSection() { + pthread_mutex_init(&mutex, NULL); +} + +//SimpleCriticalSection::~SimpleCriticalSection() { +// pthread_mutex_destroy(&mutex); +//} + diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.base/windows/native/libjimage/osSupport_windows.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/windows/native/libjimage/osSupport_windows.cpp Thu Sep 10 14:55:20 2015 -0700 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2015, 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 +#include +#include +#include +#include +#include + +#include "jni.h" +#include "osSupport.hpp" + +/** + * Open a regular file read-only. + * Return the file descriptor. + */ +jint osSupport::openReadOnly(const char *path) { + return ::open(path, 0, 0); +} + +/** + * Close a file descriptor. + */ +jint osSupport::close(jint fd) { + return ::close(fd); +} + +/** + * Return the size of a regular file. + */ +jlong osSupport::size(const char *path) { + struct stat statbuf; + if (stat(path, &statbuf) < 0 || + (statbuf.st_mode & S_IFREG) != S_IFREG) { + return -1; + } + return (jlong) statbuf.st_size; +} + +/** + * Read nBytes at offset into a buffer. + */ +jlong osSupport::read(jint fd, char *buf, jlong nBytes, jlong offset) { + OVERLAPPED ov; + DWORD nread; + BOOL result; + + ZeroMemory(&ov, sizeof (ov)); + ov.Offset = (DWORD) offset; + ov.OffsetHigh = (DWORD) (offset >> 32); + + HANDLE h = (HANDLE)::_get_osfhandle(fd); + + result = ReadFile(h, (LPVOID) buf, (DWORD) nBytes, &nread, &ov); + + return result ? nread : 0; +} + +/** + * Map nBytes at offset into memory and return the address. + * The system chooses the address. + */ +void* osSupport::map_memory(jint fd, const char *file_name, size_t file_offset, size_t bytes) { + HANDLE hFile; + char* base = NULL; + + // Get a handle to the file + hFile = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile != NULL) { + // Create a file mapping handle + HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, + NULL /* file_name */); + if (hMap != NULL) { + // Map the file into the address space at the offset + base = (char*) MapViewOfFileEx(hMap, FILE_MAP_READ, 0, (DWORD) file_offset, + (DWORD) bytes, NULL); + CloseHandle(hMap); // The mapping is no longer needed + } + CloseHandle(hFile); // The file handle is no longer needed + } + return base; +} + +/** + * Unmap nBytes of memory at address. + */ +int osSupport::unmap_memory(void* addr, size_t bytes) { + BOOL result = UnmapViewOfFile(addr); + return result; +} + +/** + * A CriticalSection to protect a small section of code. + */ +void SimpleCriticalSection::enter() { + EnterCriticalSection(&critical_section); +} + +void SimpleCriticalSection::exit() { + LeaveCriticalSection(&critical_section); +} + +SimpleCriticalSection::SimpleCriticalSection() { + InitializeCriticalSection(&critical_section); +} + +//SimpleCriticalSection::~SimpleCriticalSection() { +// DeleteCriticalSection(&critical_section); +//} + diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.management/share/classes/com/sun/jmx/remote/internal/IIOPHelper.java --- a/src/java.management/share/classes/com/sun/jmx/remote/internal/IIOPHelper.java Thu Sep 10 17:56:24 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2009, 2012, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 com.sun.jmx.remote.internal; - -import java.util.Properties; -import java.io.IOException; -import java.rmi.Remote; -import java.rmi.NoSuchObjectException; - -import java.security.AccessController; -import java.security.PrivilegedAction; - -/** - * A helper class for RMI-IIOP and CORBA APIs. - */ - -public final class IIOPHelper { - private IIOPHelper() { } - - // loads IIOPProxy implementation class if available - private static final String IMPL_CLASS = - "com.sun.jmx.remote.protocol.iiop.IIOPProxyImpl"; - private static final IIOPProxy proxy = - AccessController.doPrivileged(new PrivilegedAction() { - public IIOPProxy run() { - try { - Class c = Class.forName(IMPL_CLASS, true, - IIOPHelper.class.getClassLoader()); - return (IIOPProxy)c.newInstance(); - } catch (ClassNotFoundException cnf) { - return null; - } catch (InstantiationException e) { - throw new AssertionError(e); - } catch (IllegalAccessException e) { - throw new AssertionError(e); - } - }}); - - /** - * Returns true if RMI-IIOP and CORBA is available. - */ - public static boolean isAvailable() { - return proxy != null; - } - - private static void ensureAvailable() { - if (proxy == null) - throw new AssertionError("Should not here"); - } - - /** - * Returns true if the given object is a Stub. - */ - public static boolean isStub(Object obj) { - return (proxy == null) ? false : proxy.isStub(obj); - } - - /** - * Returns the Delegate to which the given Stub delegates. - */ - public static Object getDelegate(Object stub) { - ensureAvailable(); - return proxy.getDelegate(stub); - } - - /** - * Sets the Delegate for a given Stub. - */ - public static void setDelegate(Object stub, Object delegate) { - ensureAvailable(); - proxy.setDelegate(stub, delegate); - } - - /** - * Returns the ORB associated with the given stub - * - * @throws UnsupportedOperationException - * if the object does not support the operation that - * was invoked - */ - public static Object getOrb(Object stub) { - ensureAvailable(); - return proxy.getOrb(stub); - } - - /** - * Connects the Stub to the given ORB. - */ - public static void connect(Object stub, Object orb) - throws IOException - { - if (proxy == null) - throw new IOException("Connection to ORB failed, RMI/IIOP not available"); - proxy.connect(stub, orb); - } - - /** - * Returns true if the given object is an ORB. - */ - public static boolean isOrb(Object obj) { - return (proxy == null) ? false : proxy.isOrb(obj); - } - - /** - * Creates, and returns, a new ORB instance. - */ - public static Object createOrb(String[] args, Properties props) - throws IOException - { - if (proxy == null) - throw new IOException("ORB initialization failed, RMI/IIOP not available"); - return proxy.createOrb(args, props); - } - - /** - * Converts a string, produced by the object_to_string method, back - * to a CORBA object reference. - */ - public static Object stringToObject(Object orb, String str) { - ensureAvailable(); - return proxy.stringToObject(orb, str); - } - - /** - * Converts the given CORBA object reference to a string. - */ - public static String objectToString(Object orb, Object obj) { - ensureAvailable(); - return proxy.objectToString(orb, obj); - } - - /** - * Checks to ensure that an object of a remote or abstract interface - * type can be cast to a desired type. - */ - public static T narrow(Object narrowFrom, Class narrowTo) { - ensureAvailable(); - return proxy.narrow(narrowFrom, narrowTo); - } - - /** - * Makes a server object ready to receive remote calls - */ - public static void exportObject(Remote obj) throws IOException { - if (proxy == null) - throw new IOException("RMI object cannot be exported, RMI/IIOP not available"); - proxy.exportObject(obj); - } - - /** - * Deregisters a server object from the runtime. - */ - public static void unexportObject(Remote obj) throws IOException { - if (proxy == null) - throw new NoSuchObjectException("Object not exported"); - proxy.unexportObject(obj); - } - - /** - * Returns a stub for the given server object. - */ - public static Remote toStub(Remote obj) throws IOException { - if (proxy == null) - throw new NoSuchObjectException("Object not exported"); - return proxy.toStub(obj); - } -} diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.management/share/classes/com/sun/jmx/remote/internal/IIOPProxy.java --- a/src/java.management/share/classes/com/sun/jmx/remote/internal/IIOPProxy.java Thu Sep 10 17:56:24 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2009, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 com.sun.jmx.remote.internal; - -import java.util.Properties; -import java.rmi.Remote; -import java.rmi.RemoteException; -import java.rmi.NoSuchObjectException; - -/** - * An interface to a subset of the RMI-IIOP and CORBA APIs to avoid a - * static dependencies on the types defined by these APIs. - */ - -public interface IIOPProxy { - - /** - * Returns true if the given object is a Stub. - */ - boolean isStub(Object obj); - - /** - * Returns the Delegate to which the given Stub delegates. - */ - Object getDelegate(Object stub); - - /** - * Sets the Delegate for a given Stub. - */ - void setDelegate(Object stub, Object delegate); - - /** - * Returns the ORB associated with the given stub - * - * @throws UnsupportedOperationException - * if the object does not support the operation that - * was invoked - */ - Object getOrb(Object stub); - - /** - * Connects the Stub to the given ORB. - */ - void connect(Object stub, Object orb) throws RemoteException; - - /** - * Returns true if the given object is an ORB. - */ - boolean isOrb(Object obj); - - /** - * Creates, and returns, a new ORB instance. - */ - Object createOrb(String[] args, Properties props); - - /** - * Converts a string, produced by the object_to_string method, back - * to a CORBA object reference. - */ - Object stringToObject(Object orb, String str); - - /** - * Converts the given CORBA object reference to a string. - */ - String objectToString(Object orb, Object obj); - - /** - * Checks to ensure that an object of a remote or abstract interface - * type can be cast to a desired type. - */ - T narrow(Object narrowFrom, Class narrowTo); - - /** - * Makes a server object ready to receive remote calls - */ - void exportObject(Remote obj) throws RemoteException; - - /** - * Deregisters a server object from the runtime. - */ - void unexportObject(Remote obj) throws NoSuchObjectException; - - /** - * Returns a stub for the given server object. - */ - Remote toStub(Remote obj) throws NoSuchObjectException; -} diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.management/share/classes/com/sun/jmx/remote/protocol/iiop/ClientProvider.java --- a/src/java.management/share/classes/com/sun/jmx/remote/protocol/iiop/ClientProvider.java Thu Sep 10 17:56:24 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2003, 2004, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 com.sun.jmx.remote.protocol.iiop; - -import java.io.IOException; -import java.net.MalformedURLException; -import java.util.Map; - -import javax.management.remote.JMXConnectorProvider; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXServiceURL; -import javax.management.remote.rmi.RMIConnector; - -public class ClientProvider implements JMXConnectorProvider { - - public JMXConnector newJMXConnector(JMXServiceURL serviceURL, - Map environment) - throws IOException { - if (!serviceURL.getProtocol().equals("iiop")) { - throw new MalformedURLException("Protocol not iiop: " + - serviceURL.getProtocol()); - } - return new RMIConnector(serviceURL, environment); - } -} diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.management/share/classes/com/sun/jmx/remote/protocol/iiop/IIOPProxyImpl.java --- a/src/java.management/share/classes/com/sun/jmx/remote/protocol/iiop/IIOPProxyImpl.java Thu Sep 10 17:56:24 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2009,2013, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 com.sun.jmx.remote.protocol.iiop; - -import org.omg.CORBA.ORB; -import org.omg.CORBA.portable.Delegate; -import javax.rmi.PortableRemoteObject; -import javax.rmi.CORBA.Stub; - -import java.util.Properties; -import java.rmi.Remote; -import java.rmi.RemoteException; -import java.rmi.NoSuchObjectException; - -import com.sun.jmx.remote.internal.IIOPProxy; -import java.io.SerializablePermission; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.Permissions; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.security.ProtectionDomain; - -/** - * An implementation of IIOPProxy that simply delegates to the appropriate - * RMI-IIOP and CORBA APIs. - */ - -public class IIOPProxyImpl implements IIOPProxy { - // special ACC used to initialize the IIOP stub - // the only allowed privilege is SerializablePermission("enableSubclassImplementation") - private static final AccessControlContext STUB_ACC; - - static { - Permissions p = new Permissions(); - p.add(new SerializablePermission("enableSubclassImplementation")); - STUB_ACC = new AccessControlContext( - new ProtectionDomain[]{ - new ProtectionDomain(null, p) - } - ); - } - - public IIOPProxyImpl() { } - - @Override - public boolean isStub(Object obj) { - return (obj instanceof Stub); - } - - @Override - public Object getDelegate(Object stub) { - return ((Stub)stub)._get_delegate(); - } - - @Override - public void setDelegate(Object stub, Object delegate) { - ((Stub)stub)._set_delegate((Delegate)delegate); - } - - @Override - public Object getOrb(Object stub) { - try { - return ((Stub)stub)._orb(); - } catch (org.omg.CORBA.BAD_OPERATION x) { - throw new UnsupportedOperationException(x); - } - } - - @Override - public void connect(Object stub, Object orb) - throws RemoteException - { - ((Stub)stub).connect((ORB)orb); - } - - @Override - public boolean isOrb(Object obj) { - return (obj instanceof ORB); - } - - @Override - public Object createOrb(String[] args, Properties props) { - return ORB.init(args, props); - } - - @Override - public Object stringToObject(Object orb, String str) { - return ((ORB)orb).string_to_object(str); - } - - @Override - public String objectToString(Object orb, Object obj) { - return ((ORB)orb).object_to_string((org.omg.CORBA.Object)obj); - } - - @Override - @SuppressWarnings("unchecked") - public T narrow(Object narrowFrom, Class narrowTo) { - return (T)PortableRemoteObject.narrow(narrowFrom, narrowTo); - } - - @Override - public void exportObject(Remote obj) throws RemoteException { - PortableRemoteObject.exportObject(obj); - } - - @Override - public void unexportObject(Remote obj) throws NoSuchObjectException { - PortableRemoteObject.unexportObject(obj); - } - - @Override - public Remote toStub(final Remote obj) throws NoSuchObjectException { - if (System.getSecurityManager() == null) { - return PortableRemoteObject.toStub(obj); - } else { - try { - return AccessController.doPrivileged(new PrivilegedExceptionAction() { - - @Override - public Remote run() throws Exception { - return PortableRemoteObject.toStub(obj); - } - }, STUB_ACC); - } catch (PrivilegedActionException e) { - if (e.getException() instanceof NoSuchObjectException) { - throw (NoSuchObjectException)e.getException(); - } - throw new RuntimeException("Unexpected exception type", e.getException()); - } - } - } -} diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.management/share/classes/com/sun/jmx/remote/protocol/iiop/ProxyInputStream.java --- a/src/java.management/share/classes/com/sun/jmx/remote/protocol/iiop/ProxyInputStream.java Thu Sep 10 17:56:24 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,241 +0,0 @@ -/* - * Copyright (c) 2003, 2008, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 com.sun.jmx.remote.protocol.iiop; - -import java.io.IOException; -import java.io.Serializable; -import java.math.BigDecimal; - -import org.omg.CORBA.Any; -import org.omg.CORBA.Context; -import org.omg.CORBA.NO_IMPLEMENT; -import org.omg.CORBA.ORB; -import org.omg.CORBA.TypeCode; -import org.omg.CORBA.portable.BoxedValueHelper; - -@SuppressWarnings({"deprecation", "rawtypes"}) -public class ProxyInputStream extends org.omg.CORBA_2_3.portable.InputStream { - public ProxyInputStream(org.omg.CORBA.portable.InputStream in) { - this.in = in; - } - - public boolean read_boolean() { - return in.read_boolean(); - } - - public char read_char() { - return in.read_char(); - } - - public char read_wchar() { - return in.read_wchar(); - } - - public byte read_octet() { - return in.read_octet(); - } - - public short read_short() { - return in.read_short(); - } - - public short read_ushort() { - return in.read_ushort(); - } - - public int read_long() { - return in.read_long(); - } - - public int read_ulong() { - return in.read_ulong(); - } - - public long read_longlong() { - return in.read_longlong(); - } - - public long read_ulonglong() { - return in.read_ulonglong(); - } - - public float read_float() { - return in.read_float(); - } - - public double read_double() { - return in.read_double(); - } - - public String read_string() { - return in.read_string(); - } - - public String read_wstring() { - return in.read_wstring(); - } - - public void read_boolean_array(boolean[] value, int offset, int length) { - in.read_boolean_array(value, offset, length); - } - - public void read_char_array(char[] value, int offset, int length) { - in.read_char_array(value, offset, length); - } - - public void read_wchar_array(char[] value, int offset, int length) { - in.read_wchar_array(value, offset, length); - } - - public void read_octet_array(byte[] value, int offset, int length) { - in.read_octet_array(value, offset, length); - } - - public void read_short_array(short[] value, int offset, int length) { - in.read_short_array(value, offset, length); - } - - public void read_ushort_array(short[] value, int offset, int length) { - in.read_ushort_array(value, offset, length); - } - - public void read_long_array(int[] value, int offset, int length) { - in.read_long_array(value, offset, length); - } - - public void read_ulong_array(int[] value, int offset, int length) { - in.read_ulong_array(value, offset, length); - } - - public void read_longlong_array(long[] value, int offset, int length) { - in.read_longlong_array(value, offset, length); - } - - public void read_ulonglong_array(long[] value, int offset, int length) { - in.read_ulonglong_array(value, offset, length); - } - - public void read_float_array(float[] value, int offset, int length) { - in.read_float_array(value, offset, length); - } - - public void read_double_array(double[] value, int offset, int length) { - in.read_double_array(value, offset, length); - } - - public org.omg.CORBA.Object read_Object() { - return in.read_Object(); - } - - public TypeCode read_TypeCode() { - return in.read_TypeCode(); - } - - public Any read_any() { - return in.read_any(); - } - - /** - * @deprecated - */ - @Override - @Deprecated - public org.omg.CORBA.Principal read_Principal() { - return in.read_Principal(); - } - - @Override - public int read() throws IOException { - return in.read(); - } - - @Override - public BigDecimal read_fixed() { - return in.read_fixed(); - } - - @Override - public Context read_Context() { - return in.read_Context(); - } - - @Override - public org.omg.CORBA.Object read_Object(java.lang.Class clz) { - return in.read_Object(clz); - } - - @Override - public ORB orb() { - return in.orb(); - } - - @Override - public Serializable read_value() { - return narrow().read_value(); - } - - @Override - public Serializable read_value(Class clz) { - return narrow().read_value(clz); - } - - @Override - public Serializable read_value(BoxedValueHelper factory) { - return narrow().read_value(factory); - } - - @Override - public Serializable read_value(String rep_id) { - return narrow().read_value(rep_id); - } - - @Override - public Serializable read_value(Serializable value) { - return narrow().read_value(value); - } - - @Override - public Object read_abstract_interface() { - return narrow().read_abstract_interface(); - } - - @Override - public Object read_abstract_interface(Class clz) { - return narrow().read_abstract_interface(clz); - } - - protected org.omg.CORBA_2_3.portable.InputStream narrow() { - if (in instanceof org.omg.CORBA_2_3.portable.InputStream) - return (org.omg.CORBA_2_3.portable.InputStream) in; - throw new NO_IMPLEMENT(); - } - - public org.omg.CORBA.portable.InputStream getProxiedInputStream() { - return in; - } - - protected final org.omg.CORBA.portable.InputStream in; -} diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.management/share/classes/com/sun/jmx/remote/protocol/iiop/ServerProvider.java --- a/src/java.management/share/classes/com/sun/jmx/remote/protocol/iiop/ServerProvider.java Thu Sep 10 17:56:24 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2003, 2004, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 com.sun.jmx.remote.protocol.iiop; - -import java.io.IOException; -import java.net.MalformedURLException; -import java.util.Map; - -import javax.management.MBeanServer; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerProvider; -import javax.management.remote.JMXServiceURL; -import javax.management.remote.rmi.RMIConnectorServer; - -public class ServerProvider implements JMXConnectorServerProvider { - - public JMXConnectorServer newJMXConnectorServer(JMXServiceURL serviceURL, - Map environment, - MBeanServer mbeanServer) - throws IOException { - if (!serviceURL.getProtocol().equals("iiop")) { - throw new MalformedURLException("Protocol not iiop: " + - serviceURL.getProtocol()); - } - return new RMIConnectorServer(serviceURL, environment, mbeanServer); - } - -} diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.management/share/classes/javax/management/remote/JMXConnectorFactory.java --- a/src/java.management/share/classes/javax/management/remote/JMXConnectorFactory.java Thu Sep 10 17:56:24 2015 +0200 +++ b/src/java.management/share/classes/javax/management/remote/JMXConnectorFactory.java Thu Sep 10 14:55:20 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2015, 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 @@ -140,9 +140,7 @@ * *

Every implementation must support the RMI connector protocol with * the default RMI transport, specified with string rmi. - * An implementation may optionally support the RMI connector protocol - * with the RMI/IIOP transport, specified with the string - * iiop.

+ *

* *

Once a provider is found, the result of the * newJMXConnector method is the result of calling {@link diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.management/share/classes/javax/management/remote/JMXConnectorServerFactory.java --- a/src/java.management/share/classes/javax/management/remote/JMXConnectorServerFactory.java Thu Sep 10 17:56:24 2015 +0200 +++ b/src/java.management/share/classes/javax/management/remote/JMXConnectorServerFactory.java Thu Sep 10 14:55:20 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, 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 @@ -131,9 +131,7 @@ * *

Every implementation must support the RMI connector protocol with * the default RMI transport, specified with string rmi. - * An implementation may optionally support the RMI connector protocol - * with the RMI/IIOP transport, specified with the string - * iiop.

+ *

* *

Once a provider is found, the result of the * newJMXConnectorServer method is the result of calling diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.management/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java --- a/src/java.management/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java Thu Sep 10 17:56:24 2015 +0200 +++ b/src/java.management/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java Thu Sep 10 14:55:20 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, 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 @@ -31,12 +31,11 @@

A class loader that only knows how to define a limited number of classes, and load a limited number of other classes through delegation to another loader. It is used to get around a problem - with Serialization, in particular as used by RMI (including - RMI/IIOP). The JMX Remote API defines exactly what class loader - must be used to deserialize arguments on the server, and return - values on the client. We communicate this class loader to RMI by - setting it as the context class loader. RMI uses the context - class loader to load classes as it deserializes, which is what we + with Serialization, in particular as used by RMI. The JMX Remote API + defines exactly what class loader must be used to deserialize arguments on + the server, and return values on the client. We communicate this class + loader to RMI by setting it as the context class loader. RMI uses the + context class loader to load classes as it deserializes, which is what we want. However, before consulting the context class loader, it looks up the call stack for a class with a non-null class loader, and uses that if it finds one. So, in the standalone version of diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.management/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java --- a/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java Thu Sep 10 17:56:24 2015 +0200 +++ b/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java Thu Sep 10 14:55:20 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2015, 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 @@ -76,11 +76,10 @@ /** * Constructs a new {@link RMIConnection}. This connection can be - * used with either the JRMP or IIOP transport. This object does + * used with the JRMP transport. This object does * not export itself: it is the responsibility of the caller to * export it appropriately (see {@link - * RMIJRMPServerImpl#makeClient(String,Subject)} and {@link - * RMIIIOPServerImpl#makeClient(String,Subject)}. + * RMIJRMPServerImpl#makeClient(String,Subject)}). * * @param rmiServer The RMIServerImpl object for which this * connection is created. The behavior is unspecified if this diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.management/share/classes/javax/management/remote/rmi/RMIConnector.java --- a/src/java.management/share/classes/javax/management/remote/rmi/RMIConnector.java Thu Sep 10 17:56:24 2015 +0200 +++ b/src/java.management/share/classes/javax/management/remote/rmi/RMIConnector.java Thu Sep 10 14:55:20 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2015, 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 @@ -30,25 +30,21 @@ import com.sun.jmx.remote.internal.ClientListenerInfo; import com.sun.jmx.remote.internal.ClientNotifForwarder; import com.sun.jmx.remote.internal.ProxyRef; -import com.sun.jmx.remote.internal.IIOPHelper; import com.sun.jmx.remote.util.ClassLogger; import com.sun.jmx.remote.util.EnvHelp; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InvalidObjectException; -import java.io.NotSerializableException; import java.io.ObjectInputStream; import java.io.ObjectStreamClass; import java.io.Serializable; -import java.io.WriteAbortedException; import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Proxy; import java.net.MalformedURLException; -import java.rmi.MarshalException; import java.rmi.MarshalledObject; import java.rmi.NoSuchObjectException; import java.rmi.Remote; @@ -61,13 +57,12 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; -import java.security.PrivilegedActionException; import java.security.ProtectionDomain; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.Hashtable; import java.util.Map; -import java.util.Properties; import java.util.Set; import java.util.WeakHashMap; import javax.management.Attribute; @@ -146,22 +141,20 @@ * the RMI connector server with the given address.

* *

The address can refer directly to the connector server, - * using one of the following syntaxes:

+ * using the following syntax:

* *
      * service:jmx:rmi://[host[:port]]/stub/encoded-stub
-     * service:jmx:iiop://[host[:port]]/ior/encoded-IOR
      * 
* *

(Here, the square brackets {@code []} are not part of the * address but indicate that the host and port are optional.)

* *

The address can instead indicate where to find an RMI stub - * through JNDI, using one of the following syntaxes:

+ * through JNDI, using the following syntax:

* *
      * service:jmx:rmi://[host[:port]]/jndi/jndi-name
-     * service:jmx:iiop://[host[:port]]/jndi/jndi-name
      * 
* *

An implementation may also recognize additional address @@ -242,8 +235,7 @@ /** * @throws IOException if the connection could not be made because of a - * communication problem, or in the case of the {@code iiop} protocol, - * that RMI/IIOP is not supported + * communication problem */ public void connect() throws IOException { connect(null); @@ -251,8 +243,7 @@ /** * @throws IOException if the connection could not be made because of a - * communication problem, or in the case of the {@code iiop} protocol, - * that RMI/IIOP is not supported + * communication problem */ public synchronized void connect(Map environment) throws IOException { @@ -294,9 +285,7 @@ if (checkStub) checkStub(stub, rmiServerImplStubClass); - // Connect IIOP Stub if needed. if (tracing) logger.trace("connect",idstr + " connecting stub..."); - stub = connectStub(stub,usemap); idstr = (tracing?"["+this.toString()+"]":null); // Calling newClient on the RMIServer stub. @@ -307,18 +296,6 @@ try { connection = getConnection(stub, credentials, checkStub); } catch (java.rmi.RemoteException re) { - if (jmxServiceURL != null) { - final String pro = jmxServiceURL.getProtocol(); - final String path = jmxServiceURL.getURLPath(); - - if ("rmi".equals(pro) && - path.startsWith("/jndi/iiop:")) { - MalformedURLException mfe = new MalformedURLException( - "Protocol is rmi but JNDI scheme is iiop: " + jmxServiceURL); - mfe.initCause(re); - throw mfe; - } - } throw re; } @@ -1413,13 +1390,6 @@ if (ioe instanceof UnmarshalException) { throw ioe; // the fix of 6937053 made ClientNotifForwarder.fetchNotifs // fetch one by one with UnmarshalException - } else if (ioe instanceof MarshalException) { - // IIOP will throw MarshalException wrapping a NotSerializableException - // when a server fails to serialize a response. - MarshalException me = (MarshalException)ioe; - if (me.detail instanceof NotSerializableException) { - throw (NotSerializableException)me.detail; - } } // Not serialization problem, return. @@ -1654,9 +1624,6 @@ throw new IOException("Failed to get a RMI stub: "+ne); } - // Connect IIOP Stub if needed. - stub = connectStub(stub,env); - // Calling newClient on the RMIServer stub. Object credentials = env.get(CREDENTIALS); connection = stub.newClient(credentials); @@ -1694,103 +1661,6 @@ // Private stuff - Serialization //-------------------------------------------------------------------- /** - *

In order to be usable, an IIOP stub must be connected to an ORB. - * The stub is automatically connected to the ORB if: - *

    - *
  • It was returned by the COS naming
  • - *
  • Its server counterpart has been registered in COS naming - * through JNDI.
  • - *
- * Otherwise, it is not connected. A stub which is deserialized - * from Jini is not connected. A stub which is obtained from a - * non registered RMIIIOPServerImpl is not a connected.
- * A stub which is not connected can't be serialized, and thus - * can't be registered in Jini. A stub which is not connected can't - * be used to invoke methods on the server. - *

- * In order to palliate this, this method will connect the - * given stub if it is not yet connected. If the given - * RMIServer is not an instance of - * {@link javax.rmi.CORBA.Stub javax.rmi.CORBA.Stub}, then the - * method do nothing and simply returns that stub. Otherwise, - * this method will attempt to connect the stub to an ORB as - * follows: - *

    - *
  • This method looks in the provided environment for - * the "java.naming.corba.orb" property. If it is found, the - * referenced object (an {@link org.omg.CORBA.ORB ORB}) is used to - * connect the stub. Otherwise, a new org.omg.CORBA.ORB is created - * by calling {@link - * org.omg.CORBA.ORB#init(String[], Properties) - * org.omg.CORBA.ORB.init((String[])null,(Properties)null)}
  • - *
  • The new created ORB is kept in a static - * {@link WeakReference} and can be reused for connecting other - * stubs. However, no reference is ever kept on the ORB provided - * in the environment map, if any.
  • - *
- * @param rmiServer A RMI Server Stub. - * @param environment An environment map, possibly containing an ORB. - * @return the given stub. - * @exception IllegalArgumentException if the - * {@code java.naming.corba.orb} property is specified and - * does not point to an {@link org.omg.CORBA.ORB ORB}. - * @exception IOException if the connection to the ORB failed. - **/ - static RMIServer connectStub(RMIServer rmiServer, - Map environment) - throws IOException { - if (IIOPHelper.isStub(rmiServer)) { - try { - IIOPHelper.getOrb(rmiServer); - } catch (UnsupportedOperationException x) { - // BAD_OPERATION - IIOPHelper.connect(rmiServer, resolveOrb(environment)); - } - } - return rmiServer; - } - - /** - * Get the ORB specified by environment, or create a - * new one. - *

This method looks in the provided environment for - * the "java.naming.corba.orb" property. If it is found, the - * referenced object (an {@link org.omg.CORBA.ORB ORB}) is - * returned. Otherwise, a new org.omg.CORBA.ORB is created - * by calling {@link - * org.omg.CORBA.ORB#init(String[], java.util.Properties) - * org.omg.CORBA.ORB.init((String[])null,(Properties)null)} - *

The new created ORB is kept in a static - * {@link WeakReference} and can be reused for connecting other - * stubs. However, no reference is ever kept on the ORB provided - * in the environment map, if any. - * @param environment An environment map, possibly containing an ORB. - * @return An ORB. - * @exception IllegalArgumentException if the - * {@code java.naming.corba.orb} property is specified and - * does not point to an {@link org.omg.CORBA.ORB ORB}. - * @exception IOException if the ORB initialization failed. - **/ - static Object resolveOrb(Map environment) - throws IOException { - if (environment != null) { - final Object orb = environment.get(EnvHelp.DEFAULT_ORB); - if (orb != null && !(IIOPHelper.isOrb(orb))) - throw new IllegalArgumentException(EnvHelp.DEFAULT_ORB + - " must be an instance of org.omg.CORBA.ORB."); - if (orb != null) return orb; - } - final Object orb = - (RMIConnector.orb==null)?null:RMIConnector.orb.get(); - if (orb != null) return orb; - - final Object newOrb = - IIOPHelper.createOrb((String[])null, (Properties)null); - RMIConnector.orb = new WeakReference(newOrb); - return newOrb; - } - - /** * Read RMIConnector fields from an {@link java.io.ObjectInputStream * ObjectInputStream}. * Calls {@code s.defaultReadObject()} and then initializes @@ -1846,7 +1716,6 @@ throws IOException { if (rmiServer == null && jmxServiceURL == null) throw new InvalidObjectException("rmiServer and jmxServiceURL both null."); - connectStub(this.rmiServer,env); s.defaultWriteObject(); } @@ -1911,24 +1780,15 @@ private RMIServer findRMIServer(JMXServiceURL directoryURL, Map environment) throws NamingException, IOException { - final boolean isIiop = RMIConnectorServer.isIiopURL(directoryURL,true); - if (isIiop) { - // Make sure java.naming.corba.orb is in the Map. - environment.put(EnvHelp.DEFAULT_ORB,resolveOrb(environment)); - } String path = directoryURL.getURLPath(); int end = path.indexOf(';'); if (end < 0) end = path.length(); if (path.startsWith("/jndi/")) - return findRMIServerJNDI(path.substring(6,end), environment, isIiop); + return findRMIServerJNDI(path.substring(6,end), environment); else if (path.startsWith("/stub/")) - return findRMIServerJRMP(path.substring(6,end), environment, isIiop); - else if (path.startsWith("/ior/")) { - if (!IIOPHelper.isAvailable()) - throw new IOException("iiop protocol not available"); - return findRMIServerIIOP(path.substring(5,end), environment, isIiop); - } else { + return findRMIServerJRMP(path.substring(6,end), environment); + else { final String msg = "URL path must begin with /jndi/ or /stub/ " + "or /ior/: " + path; throw new MalformedURLException(msg); @@ -1940,16 +1800,13 @@ * @param jndiURL A JNDI URL indicating the location of the Stub * (see {@link javax.management.remote.rmi}), e.g.: *
  • {@code rmi://registry-host:port/rmi-stub-name}
  • - *
  • or {@code iiop://cosnaming-host:port/iiop-stub-name}
  • *
  • or {@code ldap://ldap-host:port/java-container-dn}
  • *
* @param env the environment Map passed to the connector. - * @param isIiop true if the stub is expected to be an IIOP stub. * @return The retrieved RMIServer stub. * @exception NamingException if the stub couldn't be found. **/ - private RMIServer findRMIServerJNDI(String jndiURL, Map env, - boolean isIiop) + private RMIServer findRMIServerJNDI(String jndiURL, Map env) throws NamingException { InitialContext ctx = new InitialContext(EnvHelp.mapToHashtable(env)); @@ -1957,10 +1814,7 @@ Object objref = ctx.lookup(jndiURL); ctx.close(); - if (isIiop) - return narrowIIOPServer(objref); - else - return narrowJRMPServer(objref); + return narrowJRMPServer(objref); } private static RMIServer narrowJRMPServer(Object objref) { @@ -1968,28 +1822,8 @@ return (RMIServer) objref; } - private static RMIServer narrowIIOPServer(Object objref) { - try { - return IIOPHelper.narrow(objref, RMIServer.class); - } catch (ClassCastException e) { - if (logger.traceOn()) - logger.trace("narrowIIOPServer","Failed to narrow objref=" + - objref + ": " + e); - if (logger.debugOn()) logger.debug("narrowIIOPServer",e); - return null; - } - } - - private RMIServer findRMIServerIIOP(String ior, Map env, boolean isIiop) { - // could forbid "rmi:" URL here -- but do we need to? - final Object orb = env.get(EnvHelp.DEFAULT_ORB); - final Object stub = IIOPHelper.stringToObject(orb, ior); - return IIOPHelper.narrow(stub, RMIServer.class); - } - - private RMIServer findRMIServerJRMP(String base64, Map env, boolean isIiop) + private RMIServer findRMIServerJRMP(String base64, Map env) throws IOException { - // could forbid "iiop:" URL here -- but do we need to? final byte[] serialized; try { serialized = base64ToByteArray(base64); @@ -2203,228 +2037,6 @@ return proxyStub; } - /* - The following code performs a similar trick for RMI/IIOP to the - one described above for RMI/JRMP. Unlike JRMP, though, we - can't easily insert an object between the RMIConnection stub - and the RMI/IIOP deserialization code, as explained below. - - A method in an RMI/IIOP stub does the following. It makes an - org.omg.CORBA_2_3.portable.OutputStream for each request, and - writes the parameters to it. Then it calls - _invoke(OutputStream) which it inherits from CORBA's - ObjectImpl. That returns an - org.omg.CORBA_2_3.portable.InputStream. The return value is - read from this InputStream. So the stack during - deserialization looks like this: - - MBeanServerConnection.getAttribute (or whatever) - -> _RMIConnection_Stub.getAttribute - -> Util.readAny (a CORBA method) - -> InputStream.read_any - -> internal CORBA stuff - - What we would have *liked* to have done would be the same thing - as for RMI/JRMP. We create a "ProxyDelegate" that is an - org.omg.CORBA.portable.Delegate that simply forwards every - operation to the real original Delegate from the RMIConnection - stub, except that the InputStream returned by _invoke is - wrapped by a "ProxyInputStream" that is loaded by our - NoCallStackClassLoader. - - Unfortunately, this doesn't work, at least with Sun's J2SE - 1.4.2, because the CORBA code is not designed to allow you to - change Delegates arbitrarily. You get a ClassCastException - from code that expects the Delegate to implement an internal - interface. - - So instead we do the following. We create a subclass of the - stub that overrides the _invoke method so as to wrap the - returned InputStream in a ProxyInputStream. We create a - subclass of ProxyInputStream using the NoCallStackClassLoader - and override its read_any and read_value(Class) methods. - (These are the only methods called during deserialization of - MBeanServerConnection return values.) We extract the Delegate - from the original stub and insert it into our subclass stub, - and away we go. The state of a stub consists solely of its - Delegate. - - We also need to catch ApplicationException, which will encode - any exceptions declared in the throws clause of the called - method. Its InputStream needs to be wrapped in a - ProxyInputSteam too. - - We override _releaseReply in the stub subclass so that it - replaces a ProxyInputStream argument with the original - InputStream. This avoids problems if the implementation of - _releaseReply ends up casting this InputStream to an - implementation-specific interface (which in Sun's J2SE 5 it - does). - - It is not strictly necessary for the stub subclass to be loaded - by a NoCallStackClassLoader, since the call-stack search stops - at the ProxyInputStream subclass. However, it is convenient - for two reasons. One is that it means that the - ProxyInputStream subclass can be accessed directly, without - using reflection. The other is that it avoids build problems, - since usually stubs are created after other classes are - compiled, so we can't access them from this class without, - again, using reflection. - - The strings below encode the following two Java classes, - compiled using javac -g:none. - - package com.sun.jmx.remote.protocol.iiop; - - import org.omg.stub.javax.management.remote.rmi._RMIConnection_Stub; - - import org.omg.CORBA.portable.ApplicationException; - import org.omg.CORBA.portable.InputStream; - import org.omg.CORBA.portable.OutputStream; - import org.omg.CORBA.portable.RemarshalException; - - public class ProxyStub extends _RMIConnection_Stub { - public InputStream _invoke(OutputStream out) - throws ApplicationException, RemarshalException { - try { - return new PInputStream(super._invoke(out)); - } catch (ApplicationException e) { - InputStream pis = new PInputStream(e.getInputStream()); - throw new ApplicationException(e.getId(), pis); - } - } - - public void _releaseReply(InputStream in) { - if (in != null) - in = ((PInputStream)in).getProxiedInputStream(); - super._releaseReply(in); - } - } - - package com.sun.jmx.remote.protocol.iiop; - - public class PInputStream extends ProxyInputStream { - public PInputStream(org.omg.CORBA.portable.InputStream in) { - super(in); - } - - public org.omg.CORBA.Any read_any() { - return in.read_any(); - } - - public java.io.Serializable read_value(Class clz) { - return narrow().read_value(clz); - } - } - - - */ - private static final String iiopConnectionStubClassName = - "org.omg.stub.javax.management.remote.rmi._RMIConnection_Stub"; - private static final String proxyStubClassName = - "com.sun.jmx.remote.protocol.iiop.ProxyStub"; - private static final String ProxyInputStreamClassName = - "com.sun.jmx.remote.protocol.iiop.ProxyInputStream"; - private static final String pInputStreamClassName = - "com.sun.jmx.remote.protocol.iiop.PInputStream"; - private static final Class proxyStubClass; - static { - final String proxyStubByteCodeString = - "\312\376\272\276\0\0\0\63\0+\12\0\14\0\30\7\0\31\12\0\14\0\32\12"+ - "\0\2\0\33\7\0\34\12\0\5\0\35\12\0\5\0\36\12\0\5\0\37\12\0\2\0 "+ - "\12\0\14\0!\7\0\"\7\0#\1\0\6\1\0\3()V\1\0\4Code\1\0\7_in"+ - "voke\1\0K(Lorg/omg/CORBA/portable/OutputStream;)Lorg/omg/CORBA"+ - "/portable/InputStream;\1\0\15StackMapTable\7\0\34\1\0\12Except"+ - "ions\7\0$\1\0\15_releaseReply\1\0'(Lorg/omg/CORBA/portable/Inp"+ - "utStream;)V\14\0\15\0\16\1\0-com/sun/jmx/remote/protocol/iiop/"+ - "PInputStream\14\0\20\0\21\14\0\15\0\27\1\0+org/omg/CORBA/porta"+ - "ble/ApplicationException\14\0%\0&\14\0'\0(\14\0\15\0)\14\0*\0&"+ - "\14\0\26\0\27\1\0*com/sun/jmx/remote/protocol/iiop/ProxyStub\1"+ - "\0\1\0'("+ - "Lorg/omg/CORBA/portable/InputStream;)V\1\0\4Code\1\0\10read_an"+ - "y\1\0\25()Lorg/omg/CORBA/Any;\1\0\12read_value\1\0)(Ljava/lang"+ - "/Class;)Ljava/io/Serializable;\14\0\10\0\11\14\0\30\0\31\7\0\32"+ - "\14\0\13\0\14\14\0\33\0\34\7\0\35\14\0\15\0\16\1\0-com/sun/jmx"+ - "/remote/protocol/iiop/PInputStream\1\0\61com/sun/jmx/remote/pr"+ - "otocol/iiop/ProxyInputStream\1\0\2in\1\0$Lorg/omg/CORBA/portab"+ - "le/InputStream;\1\0\"org/omg/CORBA/portable/InputStream\1\0\6n"+ - "arrow\1\0*()Lorg/omg/CORBA_2_3/portable/InputStream;\1\0&org/o"+ - "mg/CORBA_2_3/portable/InputStream\0!\0\6\0\7\0\0\0\0\0\3\0\1\0"+ - "\10\0\11\0\1\0\12\0\0\0\22\0\2\0\2\0\0\0\6*+\267\0\1\261\0\0\0"+ - "\0\0\1\0\13\0\14\0\1\0\12\0\0\0\24\0\1\0\1\0\0\0\10*\264\0\2\266"+ - "\0\3\260\0\0\0\0\0\1\0\15\0\16\0\1\0\12\0\0\0\25\0\2\0\2\0\0\0"+ - "\11*\266\0\4+\266\0\5\260\0\0\0\0\0\0"; - final byte[] proxyStubByteCode = - NoCallStackClassLoader.stringToBytes(proxyStubByteCodeString); - final byte[] pInputStreamByteCode = - NoCallStackClassLoader.stringToBytes(pInputStreamByteCodeString); - final String[] classNames={proxyStubClassName, pInputStreamClassName}; - final byte[][] byteCodes = {proxyStubByteCode, pInputStreamByteCode}; - final String[] otherClassNames = { - iiopConnectionStubClassName, - ProxyInputStreamClassName, - }; - if (IIOPHelper.isAvailable()) { - PrivilegedExceptionAction> action = - new PrivilegedExceptionAction>() { - public Class run() throws Exception { - Class thisClass = RMIConnector.class; - ClassLoader thisLoader = thisClass.getClassLoader(); - ProtectionDomain thisProtectionDomain = - thisClass.getProtectionDomain(); - ClassLoader cl = - new NoCallStackClassLoader(classNames, - byteCodes, - otherClassNames, - thisLoader, - thisProtectionDomain); - return cl.loadClass(proxyStubClassName); - } - }; - Class stubClass; - try { - stubClass = AccessController.doPrivileged(action); - } catch (Exception e) { - logger.error("", - "Unexpected exception making shadow IIOP stub class: "+e); - logger.debug("",e); - stubClass = null; - } - proxyStubClass = stubClass; - } else { - proxyStubClass = null; - } - } - - private static RMIConnection shadowIiopStub(Object stub) - throws InstantiationException, IllegalAccessException { - Object proxyStub = null; - try { - proxyStub = AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Object run() throws Exception { - return proxyStubClass.newInstance(); - } - }); - } catch (PrivilegedActionException e) { - throw new InternalError(); - } - IIOPHelper.setDelegate(proxyStub, IIOPHelper.getDelegate(stub)); - return (RMIConnection) proxyStub; - } private static RMIConnection getConnection(RMIServer server, Object credentials, boolean checkStub) @@ -2434,8 +2046,6 @@ try { if (c.getClass() == rmiConnectionImplStubClass) return shadowJrmpStub((RemoteObject) c); - if (c.getClass().getName().equals(iiopConnectionStubClassName)) - return shadowIiopStub(c); logger.trace("getConnection", "Did not wrap " + c.getClass() + " to foil " + "stack search for classes: class loading semantics " + diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.management/share/classes/javax/management/remote/rmi/RMIConnectorServer.java --- a/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectorServer.java Thu Sep 10 17:56:24 2015 +0200 +++ b/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectorServer.java Thu Sep 10 14:55:20 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2015, 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 @@ -27,7 +27,6 @@ import com.sun.jmx.remote.security.MBeanServerFileAccessController; -import com.sun.jmx.remote.internal.IIOPHelper; import com.sun.jmx.remote.util.ClassLogger; import com.sun.jmx.remote.util.EnvHelp; @@ -117,8 +116,8 @@ * * @exception MalformedURLException if url does not * conform to the syntax for an RMI connector, or if its protocol - * is not recognized by this implementation. Only "rmi" and "iiop" - * are valid when this constructor is used. + * is not recognized by this implementation. Only "rmi" is valid when + * this constructor is used. * * @exception IOException if the connector server cannot be created * for some reason or if it is inevitable that its {@link #start() @@ -151,8 +150,8 @@ * * @exception MalformedURLException if url does not * conform to the syntax for an RMI connector, or if its protocol - * is not recognized by this implementation. Only "rmi" and "iiop" - * are valid when this constructor is used. + * is not recognized by this implementation. Only "rmi" is valid + * when this constructor is used. * * @exception IOException if the connector server cannot be created * for some reason or if it is inevitable that its {@link #start() @@ -179,7 +178,7 @@ * consistent with the protocol type specified in url. * If this parameter is non null, the protocol type specified by * url is not constrained, and is assumed to be valid. - * Otherwise, only "rmi" and "iiop" will be recognized. + * Otherwise, only "rmi" will be recognized. * * @param mbeanServer the MBean server to which the new connector * server is attached, or null if it will be attached by being @@ -189,8 +188,8 @@ * * @exception MalformedURLException if url does not * conform to the syntax for an RMI connector, or if its protocol - * is not recognized by this implementation. Only "rmi" and "iiop" - * are recognized when rmiServerImpl is null. + * is not recognized by this implementation. Only "rmi" is recognized + * when rmiServerImpl is null. * * @exception IOException if the connector server cannot be created * for some reason or if it is inevitable that its {@link #start() @@ -208,7 +207,7 @@ IllegalArgumentException("Null JMXServiceURL"); if (rmiServerImpl == null) { final String prt = url.getProtocol(); - if (prt == null || !(prt.equals("rmi") || prt.equals("iiop"))) { + if (prt == null || !(prt.equals("rmi"))) { final String msg = "Invalid protocol type: " + prt; throw new MalformedURLException(msg); } @@ -298,11 +297,6 @@ *
  • If an RMIServerImpl was supplied to the * constructor, it is used. * - *
  • Otherwise, if the protocol part of the - * JMXServiceURL supplied to the constructor was - * iiop, an object of type {@link RMIIIOPServerImpl} - * is created. - * *
  • Otherwise, if the JMXServiceURL * was null, or its protocol part was rmi, an object * of type {@link RMIJRMPServerImpl} is created. @@ -324,21 +318,19 @@ * will not be bound to a directory. Instead, a reference to it * will be encoded in the URL path of the RMIConnectorServer * address (returned by {@link #getAddress()}). The encodings for - * rmi and iiop are described in the - * package documentation for {@link - * javax.management.remote.rmi}.

    + * rmi are described in the package documentation for + * {@link javax.management.remote.rmi}.

    * *

    The behavior when the URL path is neither empty nor a JNDI - * directory URL, or when the protocol is neither rmi - * nor iiop, is implementation defined, and may - * include throwing {@link MalformedURLException} when the - * connector server is created or when it is started.

    + * directory URL, or when the protocol is not rmi, + * is implementation defined, and may include throwing + * {@link MalformedURLException} when the connector server is created + * or when it is started.

    * * @exception IllegalStateException if the connector server has * not been attached to an MBean server. * @exception IOException if the connector server cannot be - * started, or in the case of the {@code iiop} protocol, that - * RMI/IIOP is not supported. + * started. */ public synchronized void start() throws IOException { final boolean tracing = logger.traceOn(); @@ -649,16 +641,13 @@ * Creates a new RMIServerImpl. **/ RMIServerImpl newServer() throws IOException { - final boolean iiop = isIiopURL(address,true); final int port; if (address == null) port = 0; else port = address.getPort(); - if (iiop) - return newIIOPServer(attributes); - else - return newJRMPServer(attributes, port); + + return newJRMPServer(attributes, port); } /** @@ -675,10 +664,7 @@ final int port; if (address == null) { - if (IIOPHelper.isStub(rmiServer)) - protocol = "iiop"; - else - protocol = "rmi"; + protocol = "rmi"; host = null; // will default to local host name port = 0; } else { @@ -692,31 +678,12 @@ address = new JMXServiceURL(protocol, host, port, urlPath); } - static boolean isIiopURL(JMXServiceURL directoryURL, boolean strict) - throws MalformedURLException { - String protocol = directoryURL.getProtocol(); - if (protocol.equals("rmi")) - return false; - else if (protocol.equals("iiop")) - return true; - else if (strict) { - - throw new MalformedURLException("URL must have protocol " + - "\"rmi\" or \"iiop\": \"" + - protocol + "\""); - } - return false; - } - /** * Returns the IOR of the given rmiServer. **/ static String encodeStub( RMIServer rmiServer, Map env) throws IOException { - if (IIOPHelper.isStub(rmiServer)) - return "/ior/" + encodeIIOPStub(rmiServer, env); - else - return "/stub/" + encodeJRMPStub(rmiServer, env); + return "/stub/" + encodeJRMPStub(rmiServer, env); } static String encodeJRMPStub( @@ -730,17 +697,6 @@ return byteArrayToBase64(bytes); } - static String encodeIIOPStub( - RMIServer rmiServer, Map env) - throws IOException { - try { - Object orb = IIOPHelper.getOrb(rmiServer); - return IIOPHelper.objectToString(orb, rmiServer); - } catch (RuntimeException x) { - throw newIOException(x.getMessage(), x); - } - } - /** * Object that we will bind to the registry. * This object is a stub connected to our RMIServerImpl. @@ -748,8 +704,7 @@ private static RMIServer objectToBind( RMIServerImpl rmiServer, Map env) throws IOException { - return RMIConnector. - connectStub((RMIServer)rmiServer.toStub(),env); + return (RMIServer)rmiServer.toStub(); } private static RMIServerImpl newJRMPServer(Map env, int port) @@ -761,11 +716,6 @@ return new RMIJRMPServerImpl(port, csf, ssf, env); } - private static RMIServerImpl newIIOPServer(Map env) - throws IOException { - return new RMIIIOPServerImpl(env); - } - private static String byteArrayToBase64(byte[] a) { int aLen = a.length; int numFullGroups = aLen/3; diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.management/share/classes/javax/management/remote/rmi/RMIIIOPServerImpl.java --- a/src/java.management/share/classes/javax/management/remote/rmi/RMIIIOPServerImpl.java Thu Sep 10 17:56:24 2015 +0200 +++ b/src/java.management/share/classes/javax/management/remote/rmi/RMIIIOPServerImpl.java Thu Sep 10 14:55:20 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, 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 @@ -27,16 +27,9 @@ import java.io.IOException; import java.rmi.Remote; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import java.util.Map; -import java.util.Collections; import javax.security.auth.Subject; -import com.sun.jmx.remote.internal.IIOPHelper; - /** *

    An {@link RMIServerImpl} that is exported through IIOP and that * creates client connections as RMI objects exported through IIOP. @@ -45,120 +38,59 @@ * @see RMIServerImpl * * @since 1.5 + * @deprecated This transport is no longer supported. */ +@Deprecated public class RMIIIOPServerImpl extends RMIServerImpl { /** - *

    Creates a new {@link RMIServerImpl}.

    + * Throws {@linkplain UnsupportedOperationException} * * @param env the environment containing attributes for the new * RMIServerImpl. Can be null, which is equivalent * to an empty Map. * - * @exception IOException if the RMI object cannot be created. + * @throws IOException if the RMI object cannot be created. */ public RMIIIOPServerImpl(Map env) throws IOException { super(env); - this.env = (env == null) ? Collections.emptyMap() : env; - - callerACC = AccessController.getContext(); + throw new UnsupportedOperationException(); } + @Override protected void export() throws IOException { - IIOPHelper.exportObject(this); + throw new UnsupportedOperationException("Method not supported. JMX RMI-IIOP is deprecated"); } + @Override protected String getProtocol() { return "iiop"; } - /** - *

    Returns an IIOP stub.

    - * The stub might not yet be connected to the ORB. The stub will - * be serializable only if it is connected to the ORB. - * @return an IIOP stub. - * @exception IOException if the stub cannot be created - e.g the - * RMIIIOPServerImpl has not been exported yet. - **/ + @Override public Remote toStub() throws IOException { - // javax.rmi.CORBA.Stub stub = - // (javax.rmi.CORBA.Stub) PortableRemoteObject.toStub(this); - final Remote stub = IIOPHelper.toStub(this); - // java.lang.System.out.println("NON CONNECTED STUB " + stub); - // org.omg.CORBA.ORB orb = - // org.omg.CORBA.ORB.init((String[])null, (Properties)null); - // stub.connect(orb); - // java.lang.System.out.println("CONNECTED STUB " + stub); - return stub; + throw new UnsupportedOperationException(); } - /** - *

    Creates a new client connection as an RMI object exported - * through IIOP. - * - * @param connectionId the ID of the new connection. Every - * connection opened by this connector server will have a - * different ID. The behavior is unspecified if this parameter is - * null. - * - * @param subject the authenticated subject. Can be null. - * - * @return the newly-created RMIConnection. - * - * @exception IOException if the new client object cannot be - * created or exported. - */ + @Override protected RMIConnection makeClient(String connectionId, Subject subject) throws IOException { - - if (connectionId == null) - throw new NullPointerException("Null connectionId"); - - RMIConnection client = - new RMIConnectionImpl(this, connectionId, getDefaultClassLoader(), - subject, env); - IIOPHelper.exportObject(client); - return client; + throw new UnsupportedOperationException(); } + @Override protected void closeClient(RMIConnection client) throws IOException { - IIOPHelper.unexportObject(client); + throw new UnsupportedOperationException(); } - /** - *

    Called by {@link #close()} to close the connector server by - * unexporting this object. After returning from this method, the - * connector server must not accept any new connections.

    - * - * @exception IOException if the attempt to close the connector - * server failed. - */ + @Override protected void closeServer() throws IOException { - IIOPHelper.unexportObject(this); + throw new UnsupportedOperationException(); } @Override RMIConnection doNewClient(final Object credentials) throws IOException { - if (callerACC == null) { - throw new SecurityException("AccessControlContext cannot be null"); - } - try { - return AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public RMIConnection run() throws IOException { - return superDoNewClient(credentials); - } - }, callerACC); - } catch (PrivilegedActionException pae) { - throw (IOException) pae.getCause(); - } + throw new UnsupportedOperationException(); } - - RMIConnection superDoNewClient(Object credentials) throws IOException { - return super.doNewClient(credentials); - } - - private final Map env; - private final AccessControlContext callerACC; } diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.management/share/classes/javax/management/remote/rmi/RMIServerImpl.java --- a/src/java.management/share/classes/javax/management/remote/rmi/RMIServerImpl.java Thu Sep 10 17:56:24 2015 +0200 +++ b/src/java.management/share/classes/javax/management/remote/rmi/RMIServerImpl.java Thu Sep 10 14:55:20 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2015, 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 @@ -61,8 +61,7 @@ * or by instantiating {@link RMIConnector}.

    * *

    This is an abstract class. Concrete subclasses define the - * details of the client connection objects, such as whether they use - * JRMP or IIOP.

    + * details of the client connection objects.

    * * @since 1.5 */ @@ -307,7 +306,7 @@ /** *

    Returns the protocol string for this object. The string is - * rmi for RMI/JRMP and iiop for RMI/IIOP. + * rmi for RMI/JRMP. * * @return the protocol string for this object. */ diff -r 4b948e5a3e77 -r 7ecf45f5fa46 src/java.management/share/classes/javax/management/remote/rmi/package.html --- a/src/java.management/share/classes/javax/management/remote/rmi/package.html Thu Sep 10 17:56:24 2015 +0200 +++ b/src/java.management/share/classes/javax/management/remote/rmi/package.html Thu Sep 10 14:55:20 2015 -0700 @@ -2,7 +2,7 @@ RMI connector