mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-19 18:44:38 +02:00
8254231: Implementation of Foreign Linker API (Incubator)
Reviewed-by: coleenp, ihse, dholmes, vlivanov
This commit is contained in:
parent
53f38353e0
commit
0fb31dbf3a
212 changed files with 67390 additions and 179 deletions
|
@ -605,6 +605,10 @@ public abstract class MethodHandle implements Constable {
|
|||
/*non-public*/
|
||||
static native @PolymorphicSignature Object linkToInterface(Object... args) throws Throwable;
|
||||
|
||||
/** TODO */
|
||||
@IntrinsicCandidate
|
||||
/*non-public*/ static native @PolymorphicSignature Object linkToNative(Object... args) throws Throwable;
|
||||
|
||||
/**
|
||||
* Performs a variable arity invocation, passing the arguments in the given array
|
||||
* to the method handle, as if via an inexact {@link #invoke invoke} from a call site
|
||||
|
|
|
@ -27,6 +27,7 @@ package java.lang.invoke;
|
|||
|
||||
import jdk.internal.access.JavaLangInvokeAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.invoke.NativeEntryPoint;
|
||||
import jdk.internal.org.objectweb.asm.ClassWriter;
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
import jdk.internal.reflect.CallerSensitive;
|
||||
|
@ -1774,6 +1775,11 @@ abstract class MethodHandleImpl {
|
|||
return VarHandles.makeMemoryAddressViewHandle(carrier, skipAlignmentMaskCheck, alignmentMask, order);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodHandle nativeMethodHandle(NativeEntryPoint nep, MethodHandle fallback) {
|
||||
return NativeMethodHandle.make(nep, fallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VarHandle filterValue(VarHandle target, MethodHandle filterToTarget, MethodHandle filterFromTarget) {
|
||||
return VarHandles.filterValue(target, filterToTarget, filterFromTarget);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2020, 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
|
||||
|
@ -86,7 +86,8 @@ final class MethodTypeForm {
|
|||
LF_TF = 18, // tryFinally
|
||||
LF_LOOP = 19, // loop
|
||||
LF_INVSPECIAL_IFC = 20, // DMH invokeSpecial of (private) interface method
|
||||
LF_LIMIT = 21;
|
||||
LF_INVNATIVE = 21, // NMH invokeNative
|
||||
LF_LIMIT = 22;
|
||||
|
||||
/** Return the type corresponding uniquely (1-1) to this MT-form.
|
||||
* It might have any primitive returns or arguments, but will have no references except Object.
|
||||
|
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 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 java.lang.invoke;
|
||||
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
import jdk.internal.invoke.NativeEntryPoint;
|
||||
|
||||
import static java.lang.invoke.LambdaForm.*;
|
||||
import static java.lang.invoke.MethodHandleNatives.Constants.LM_TRUSTED;
|
||||
import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
|
||||
import static java.lang.invoke.MethodHandleStatics.newInternalError;
|
||||
|
||||
/**
|
||||
* This class models a method handle to a native function. A native method handle is made up of a {@link NativeEntryPoint},
|
||||
* which is used to capture the characteristics of the native call (such as calling convention to be used,
|
||||
* or whether a native transition is required) and a <em>fallback</em> method handle, which can be used
|
||||
* when intrinsification of this method handle is not possible.
|
||||
*/
|
||||
/*non-public*/ class NativeMethodHandle extends MethodHandle {
|
||||
final NativeEntryPoint nep;
|
||||
final MethodHandle fallback;
|
||||
|
||||
private NativeMethodHandle(MethodType type, LambdaForm form, MethodHandle fallback, NativeEntryPoint nep) {
|
||||
super(type, form);
|
||||
this.fallback = fallback;
|
||||
this.nep = nep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new native method handle with given {@link NativeEntryPoint} and <em>fallback</em> method handle.
|
||||
*/
|
||||
public static MethodHandle make(NativeEntryPoint nep, MethodHandle fallback) {
|
||||
MethodType type = nep.type();
|
||||
if (!allTypesPrimitive(type))
|
||||
throw new IllegalArgumentException("Type must only contain primitives: " + type);
|
||||
|
||||
if (type != fallback.type())
|
||||
throw new IllegalArgumentException("Type of fallback must match");
|
||||
|
||||
LambdaForm lform = preparedLambdaForm(type);
|
||||
return new NativeMethodHandle(type, lform, fallback, nep);
|
||||
}
|
||||
|
||||
private static boolean allTypesPrimitive(MethodType type) {
|
||||
if (!type.returnType().isPrimitive())
|
||||
return false;
|
||||
|
||||
for (Class<?> pType : type.parameterArray()) {
|
||||
if (!pType.isPrimitive())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
|
||||
|
||||
private static LambdaForm preparedLambdaForm(MethodType mtype) {
|
||||
int id = MethodTypeForm.LF_INVNATIVE;
|
||||
mtype = mtype.basicType();
|
||||
LambdaForm lform = mtype.form().cachedLambdaForm(id);
|
||||
if (lform != null) return lform;
|
||||
lform = makePreparedLambdaForm(mtype);
|
||||
return mtype.form().setCachedLambdaForm(id, lform);
|
||||
}
|
||||
|
||||
private static LambdaForm makePreparedLambdaForm(MethodType mtype) {
|
||||
MethodType linkerType = mtype.insertParameterTypes(0, MethodHandle.class)
|
||||
.appendParameterTypes(Object.class);
|
||||
MemberName linker = new MemberName(MethodHandle.class, "linkToNative", linkerType, REF_invokeStatic);
|
||||
try {
|
||||
linker = IMPL_NAMES.resolveOrFail(REF_invokeStatic, linker, null, LM_TRUSTED, NoSuchMethodException.class);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw newInternalError(ex);
|
||||
}
|
||||
final int NMH_THIS = 0;
|
||||
final int ARG_BASE = 1;
|
||||
final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
|
||||
int nameCursor = ARG_LIMIT;
|
||||
final int GET_FALLBACK = nameCursor++;
|
||||
final int GET_NEP = nameCursor++;
|
||||
final int LINKER_CALL = nameCursor++;
|
||||
LambdaForm.Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
|
||||
assert (names.length == nameCursor);
|
||||
names[GET_FALLBACK] = new LambdaForm.Name(Lazy.NF_internalFallback, names[NMH_THIS]);
|
||||
names[GET_NEP] = new LambdaForm.Name(Lazy.NF_internalNativeEntryPoint, names[NMH_THIS]);
|
||||
Object[] outArgs = new Object[linkerType.parameterCount()];
|
||||
// Need to pass fallback here so we can call it without destroying the receiver register!!
|
||||
outArgs[0] = names[GET_FALLBACK];
|
||||
System.arraycopy(names, ARG_BASE, outArgs, 1, mtype.parameterCount());
|
||||
outArgs[outArgs.length - 1] = names[GET_NEP];
|
||||
names[LINKER_CALL] = new LambdaForm.Name(linker, outArgs);
|
||||
LambdaForm lform = new LambdaForm(ARG_LIMIT, names, LAST_RESULT);
|
||||
// This is a tricky bit of code. Don't send it through the LF interpreter.
|
||||
lform.compileToBytecode();
|
||||
return lform;
|
||||
}
|
||||
|
||||
final
|
||||
@Override
|
||||
MethodHandle copyWith(MethodType mt, LambdaForm lf) {
|
||||
assert (this.getClass() == NativeMethodHandle.class); // must override in subclasses
|
||||
return new NativeMethodHandle(mt, lf, fallback, nep);
|
||||
}
|
||||
|
||||
@Override
|
||||
BoundMethodHandle rebind() {
|
||||
return BoundMethodHandle.makeReinvoker(this);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static Object internalNativeEntryPoint(Object mh) {
|
||||
return ((NativeMethodHandle)mh).nep;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static MethodHandle internalFallback(Object mh) {
|
||||
return ((NativeMethodHandle)mh).fallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-initialized NamedFunctions for bootstrapping purposes.
|
||||
* Factored in an inner class to delay initialization until first usage.
|
||||
*/
|
||||
private static class Lazy {
|
||||
|
||||
static final NamedFunction
|
||||
NF_internalNativeEntryPoint;
|
||||
static final NamedFunction
|
||||
NF_internalFallback;
|
||||
|
||||
static {
|
||||
try {
|
||||
Class<NativeMethodHandle> THIS_CLASS = NativeMethodHandle.class;
|
||||
NamedFunction[] nfs = new NamedFunction[]{
|
||||
NF_internalNativeEntryPoint = new NamedFunction(
|
||||
THIS_CLASS.getDeclaredMethod("internalNativeEntryPoint", Object.class)),
|
||||
NF_internalFallback = new NamedFunction(
|
||||
THIS_CLASS.getDeclaredMethod("internalFallback", Object.class))
|
||||
};
|
||||
for (NamedFunction nf : nfs) {
|
||||
// Each nf must be statically invocable or we get tied up in our bootstraps.
|
||||
assert (InvokerBytecodeGenerator.isStaticallyInvocable(nf.member)) : nf;
|
||||
nf.resolve();
|
||||
}
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw newInternalError(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2020, 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
|
||||
|
@ -25,6 +25,8 @@
|
|||
|
||||
package jdk.internal.access;
|
||||
|
||||
import jdk.internal.invoke.NativeEntryPoint;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.invoke.VarHandle;
|
||||
|
@ -119,4 +121,15 @@ public interface JavaLangInvokeAccess {
|
|||
* Used by {@code jdk.incubator.foreign.MemoryHandles}.
|
||||
*/
|
||||
VarHandle insertCoordinates(VarHandle target, int pos, Object... values);
|
||||
|
||||
/**
|
||||
* Returns a native method handle with given arguments as fallback and steering info.
|
||||
*
|
||||
* Will allow JIT to intrinsify.
|
||||
*
|
||||
* @param nep the native entry point
|
||||
* @param fallback the fallback handle
|
||||
* @return the native method handle
|
||||
*/
|
||||
MethodHandle nativeMethodHandle(NativeEntryPoint nep, MethodHandle fallback);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 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.access.foreign;
|
||||
|
||||
public interface NativeLibraryProxy {
|
||||
long lookup(String name) throws NoSuchMethodException;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 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.invoke;
|
||||
|
||||
public interface ABIDescriptorProxy {
|
||||
int shadowSpaceBytes();
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 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.invoke;
|
||||
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* This class describes a native call, including arguments/return shuffle moves, PC entry point and
|
||||
* various other info which are relevant when the call will be intrinsified by C2.
|
||||
*/
|
||||
public class NativeEntryPoint {
|
||||
static {
|
||||
registerNatives();
|
||||
}
|
||||
|
||||
private final long addr;
|
||||
|
||||
private final int shadowSpace;
|
||||
|
||||
// encoded as VMRegImpl*
|
||||
private final long[] argMoves;
|
||||
private final long[] returnMoves;
|
||||
|
||||
private final boolean needTransition;
|
||||
private final MethodType methodType; // C2 sees erased version (byte -> int), so need this explicitly
|
||||
private final String name;
|
||||
|
||||
private NativeEntryPoint(long addr, int shadowSpace, long[] argMoves, long[] returnMoves,
|
||||
boolean needTransition, MethodType methodType, String name) {
|
||||
this.addr = addr;
|
||||
this.shadowSpace = shadowSpace;
|
||||
this.argMoves = Objects.requireNonNull(argMoves);
|
||||
this.returnMoves = Objects.requireNonNull(returnMoves);
|
||||
this.needTransition = needTransition;
|
||||
this.methodType = methodType;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public static NativeEntryPoint make(long addr, String name, ABIDescriptorProxy abi, VMStorageProxy[] argMoves, VMStorageProxy[] returnMoves,
|
||||
boolean needTransition, MethodType methodType) {
|
||||
if (returnMoves.length > 1) {
|
||||
throw new IllegalArgumentException("Multiple register return not supported");
|
||||
}
|
||||
|
||||
return new NativeEntryPoint(
|
||||
addr, abi.shadowSpaceBytes(), encodeVMStorages(argMoves), encodeVMStorages(returnMoves), needTransition, methodType, name);
|
||||
}
|
||||
|
||||
private static long[] encodeVMStorages(VMStorageProxy[] moves) {
|
||||
long[] out = new long[moves.length];
|
||||
for (int i = 0; i < moves.length; i++) {
|
||||
out[i] = vmStorageToVMReg(moves[i].type(), moves[i].index());
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static native long vmStorageToVMReg(int type, int index);
|
||||
|
||||
public MethodType type() {
|
||||
return methodType;
|
||||
}
|
||||
|
||||
private static native void registerNatives();
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 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.invoke;
|
||||
|
||||
public interface VMStorageProxy {
|
||||
int type();
|
||||
int index();
|
||||
}
|
|
@ -384,6 +384,20 @@ public final class NativeLibraries {
|
|||
}
|
||||
}
|
||||
|
||||
public static final NativeLibrary defaultLibrary = new NativeLibraryImpl(Object.class, "<default>", true, true) {
|
||||
|
||||
@Override
|
||||
boolean open() {
|
||||
throw new UnsupportedOperationException("Cannot load default library");
|
||||
}
|
||||
|
||||
@Override
|
||||
public long find(String name) {
|
||||
return NativeLibraries.findEntryInProcess(name);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* The run() method will be invoked when this class loader becomes
|
||||
* phantom reachable to unload the native library.
|
||||
|
@ -464,4 +478,5 @@ public final class NativeLibraries {
|
|||
private static native void unload(String name, boolean isBuiltin, boolean isJNI, long handle);
|
||||
private static native String findBuiltinLib(String name);
|
||||
private static native long findEntry0(NativeLibraryImpl lib, String name);
|
||||
private static native long findEntryInProcess(String name);
|
||||
}
|
||||
|
|
|
@ -164,7 +164,8 @@ module java.base {
|
|||
exports jdk.internal.loader to
|
||||
java.instrument,
|
||||
java.logging,
|
||||
java.naming;
|
||||
java.naming,
|
||||
jdk.incubator.foreign;
|
||||
exports jdk.internal.jmod to
|
||||
jdk.compiler,
|
||||
jdk.jlink;
|
||||
|
@ -351,6 +352,8 @@ module java.base {
|
|||
java.prefs;
|
||||
exports sun.util.resources to
|
||||
jdk.localedata;
|
||||
exports jdk.internal.invoke to
|
||||
jdk.incubator.foreign;
|
||||
|
||||
|
||||
// the service types defined by the APIs in this module
|
||||
|
|
|
@ -246,6 +246,29 @@ Java_jdk_internal_loader_NativeLibraries_findEntry0
|
|||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: jdk_internal_loader_NativeLibraries
|
||||
* Method: findEntryInProcess
|
||||
* Signature: (Ljava/lang/String;)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_jdk_internal_loader_NativeLibraries_findEntryInProcess
|
||||
(JNIEnv *env, jclass cls, jstring name)
|
||||
{
|
||||
const char *cname;
|
||||
jlong res;
|
||||
|
||||
if (!initIDs(env))
|
||||
return jlong_zero;
|
||||
|
||||
cname = (*env)->GetStringUTFChars(env, name, 0);
|
||||
if (cname == 0)
|
||||
return jlong_zero;
|
||||
res = ptr_to_jlong(findEntryInProcess(cname));
|
||||
(*env)->ReleaseStringUTFChars(env, name, cname);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: jdk_internal_loader_NativeLibraries
|
||||
* Method: findBuiltinLib
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2020, 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
|
||||
|
@ -333,6 +333,8 @@ JNIEXPORT void InitializeEncoding(JNIEnv *env, const char *name);
|
|||
|
||||
void* getProcessHandle();
|
||||
|
||||
void* findEntryInProcess(const char* name);
|
||||
|
||||
void buildJniFunctionName(const char *sym, const char *cname,
|
||||
char *jniEntryName);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2020, 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
|
||||
|
@ -26,6 +26,7 @@
|
|||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jvm.h"
|
||||
#include "jni.h"
|
||||
#include "jni_util.h"
|
||||
#include "dlfcn.h"
|
||||
|
@ -50,6 +51,10 @@ void* getProcessHandle() {
|
|||
return procHandle;
|
||||
}
|
||||
|
||||
void* findEntryInProcess(const char* name) {
|
||||
return JVM_FindLibraryEntry(RTLD_DEFAULT, name);
|
||||
}
|
||||
|
||||
void buildJniFunctionName(const char *sym, const char *cname,
|
||||
char *jniEntryName) {
|
||||
strcpy(jniEntryName, sym);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include "jni.h"
|
||||
|
@ -35,6 +36,31 @@ void* getProcessHandle() {
|
|||
return (void*)GetModuleHandle(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Windows doesn't have an RTLD_DEFAULT equivalent, so in stead we have to
|
||||
* iterate over all the modules loaded by the process to implement the
|
||||
* default library behaviour.
|
||||
*/
|
||||
void* findEntryInProcess(const char* name) {
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
|
||||
HMODULE hMods[1024];
|
||||
DWORD cbNeeded; // array size in bytes
|
||||
|
||||
// first come, first served
|
||||
if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) {
|
||||
for (int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
|
||||
HMODULE mod = hMods[i];
|
||||
FARPROC proc = GetProcAddress(mod, name);
|
||||
if(proc != NULL) {
|
||||
return proc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Windows symbols can be simple like JNI_OnLoad or __stdcall format
|
||||
* like _JNI_OnLoad@8. We need to handle both.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue