8137056: Move SharedSecrets and interface friends out of sun.misc
Reviewed-by: alanb, mchung, psandoz, rriggs
/*
* 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
* 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 jdk.internal.jimage;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public final class ImageNativeSubstrate implements ImageSubstrate {
static {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
@Override
public Void run() {
System.loadLibrary("jimage");
return null;
}
});
}
// TODO: Reinstate when the class below, NIOACCESS, is removed.
//private static final JavaNioAccess NIOACCESS =
// SharedSecrets.getJavaNioAccess();
private final long id;
private final long indexAddress;
private final long dataAddress;
static native long openImage(String imagePath, boolean bigEndian);
static native void closeImage(long id);
static native long getIndexAddress(long id);
static native long getDataAddress(long id);
static native boolean readCompressed(long id, long offset,
ByteBuffer compressedBuffer, long compressedSize,
ByteBuffer uncompressedBuffer, long uncompressedSize);
static native boolean read(long id, long offset,
ByteBuffer uncompressedBuffer, long uncompressedSize);
static native byte[] getStringBytes(long id, int offset);
static native long[] getAttributes(long id, int offset);
static native long[] findAttributes(long id, byte[] path);
static native int[] attributeOffsets(long id);
public static native long JIMAGE_Open(String path) throws IOException;
public static native void JIMAGE_Close(long jimageHandle);
public static native long JIMAGE_FindResource(long jimageHandle,
String moduleName, String Version, String path,
long[] size);
public static native 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 static native int JIMAGE_Resources(long jimageHandle,
String[] outputNames);
// Return the module name for the package
public static native 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);
}
private ImageNativeSubstrate(long id) {
this.id = id;
this.indexAddress = getIndexAddress(id);
this.dataAddress = getDataAddress(id);
}
static ImageSubstrate openImage(String imagePath, ByteOrder byteOrder)
throws IOException {
long id = openImage(imagePath, byteOrder == ByteOrder.BIG_ENDIAN);
if (id == 0) {
throw new IOException("Image not found \"" + imagePath + "\"");
}
return new ImageNativeSubstrate(id);
}
@Override
public void close() {
closeImage(id);
}
@Override
public ByteBuffer getIndexBuffer(long offset, long size) {
return newDirectByteBuffer(indexAddress + offset, size);
}
@Override
public ByteBuffer getDataBuffer(long offset, long size) {
return dataAddress != 0 ?
newDirectByteBuffer(dataAddress + offset, size) : null;
}
@Override
public boolean supportsDataBuffer() {
return dataAddress != 0;
}
@Override
public boolean read(long offset,
ByteBuffer compressedBuffer, long compressedSize,
ByteBuffer uncompressedBuffer, long uncompressedSize) {
return readCompressed(id, offset,
compressedBuffer, compressedSize,
uncompressedBuffer, uncompressedSize);
}
@Override
public boolean read(long offset,
ByteBuffer uncompressedBuffer, long uncompressedSize) {
return read(id, offset, uncompressedBuffer, uncompressedSize);
}
@Override
public byte[] getStringBytes(int offset) {
byte[] ret = getStringBytes(id, offset);
if (ret == null) {
throw new OutOfMemoryError("Error accessing array at offset "
+ offset);
}
return ret;
}
@Override
public long[] getAttributes(int offset) {
return getAttributes(id, offset);
}
@Override
public ImageLocation findLocation(UTF8String name, ImageStringsReader strings) {
long[] attributes = findAttributes(id, name.getBytes());
return attributes != null ? new ImageLocation(attributes, strings) : null;
}
@Override
public int[] attributeOffsets() {
return attributeOffsets(id);
}
// TODO: Remove when JRT-FS no longer indirectly depends on ImageNativeSubstrate
/**
* Reflective wrapper around ShareSecrets JavaNioAccess.
*
* SharedSecrets and friend interfaces moved from 'sun.misc' to 'jdk.internal.misc'
* in 1.9. This class provides the runtime with access to the appropriate
* JavaNioAccess methods whether running on 1.9, or lower.
*/
static class NIOACCESS {
private static final String PKG_PREFIX = "jdk.internal.misc";
private static final String LEGACY_PKG_PREFIX = "sun.misc";
private static final Object javaNioAccess;
private static final java.lang.reflect.Method newDirectByteBufferMethod;
static {
try {
Class<?> c = getJDKClass("JavaNioAccess");
java.lang.reflect.Method m =
getJDKClass("SharedSecrets").getDeclaredMethod("getJavaNioAccess");
javaNioAccess = m.invoke(null);
newDirectByteBufferMethod = c.getDeclaredMethod("newDirectByteBuffer",
long.class,
int.class,
Object.class);
} catch (ReflectiveOperationException x) {
throw new InternalError(x);
}
}
private static Class<?> getJDKClass(String name) throws ClassNotFoundException {
try {
return Class.forName(PKG_PREFIX + "." + name);
} catch (ClassNotFoundException x) {
try {
return Class.forName(LEGACY_PKG_PREFIX + "." + name);
} catch (ClassNotFoundException ex) {
x.addSuppressed(ex);
throw x;
}
}
}
static ByteBuffer newDirectByteBuffer(long addr, int cap, Object ob) {
try {
return (ByteBuffer) newDirectByteBufferMethod.invoke(javaNioAccess, addr, cap, ob);
} catch (ReflectiveOperationException x) {
throw new InternalError(x);
}
}
}
}