Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@ NOTE: as of JNA 4.0, JNA is now dual-licensed under LGPL and AL 2.0 (see LICENSE

NOTE: JNI native support is typically incompatible between minor versions, and almost always incompatible between major versions.

Next Release (5.20.0)
Next Release (5.19.1)
=====================

Features
--------

Bug Fixes
---------

* [#1730](https://github.com/java-native-access/jna/issues/1730): Replace usage of `MethodHandle` with reflection to restore support for older Android releases - [@matthiasblaesing](https://github.com/matthiasblaesing).

Release 5.19.0
==============
Expand Down
4 changes: 2 additions & 2 deletions common.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

<!-- JNA library release version - android versionCode is derived from mjar/minor/revision -->
<property name="jna.major" value="5"/>
<property name="jna.minor" value="20"/>
<property name="jna.revision" value="0"/>
<property name="jna.minor" value="19"/>
<property name="jna.revision" value="1"/>
<property name="jna.build" value="0"/> <!--${build.number}-->
<condition property="version.suffix" value="" else="-SNAPSHOT">
<or>
Expand Down
46 changes: 20 additions & 26 deletions src/com/sun/jna/Native.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,10 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
Expand Down Expand Up @@ -184,15 +181,15 @@ public void uncaughtException(Callback c, Throwable e) {
private static final int TYPE_BOOL = 4;
private static final int TYPE_LONG_DOUBLE = 5;

private static final MethodHandle stackWalkerGetInstance;
private static final Method stackWalkerGetInstance;
private static final Enum stackWalkerRetainClassReference;
private static final MethodHandle stackWalkerWalk;
private static final Method stackWalkerWalk;
private static final Object stackWalkerFilter;

private static final MethodHandle securityManagerExposerConstructor;
private static final MethodHandle securityManagerGetClassContext;
private static final Constructor securityManagerExposerConstructor;
private static final Method securityManagerGetClassContext;

private static final MethodHandle accessControllerDoPrivileged;
private static final Method accessControllerDoPrivileged;

static final int MAX_ALIGNMENT;
static final int MAX_PADDING;
Expand Down Expand Up @@ -270,18 +267,17 @@ static boolean isCompatibleVersion(String expectedVersion, String nativeVersion)
MAX_PADDING = (Platform.isMac() && Platform.isPPC()) ? 8 : MAX_ALIGNMENT;

Enum stackWalkerRetainClassReferenceBuilder;
MethodHandle stackWalkerGetInstanceBuilder;
MethodHandle stackWalkerWalkBuilder;
Method stackWalkerGetInstanceBuilder;
Method stackWalkerWalkBuilder;
Object stackWalkerFilterBuilder;
try {
Lookup lookup = MethodHandles.lookup();
Class<?> stackWalkerClass = Class.forName("java.lang.StackWalker");
Class<? extends Enum> stackWalkerOptionClass = (Class<? extends Enum>) Class.forName("java.lang.StackWalker$Option");
stackWalkerRetainClassReferenceBuilder = Enum.valueOf(stackWalkerOptionClass, "RETAIN_CLASS_REFERENCE");
stackWalkerGetInstanceBuilder = lookup.findStatic(stackWalkerClass, "getInstance", MethodType.methodType(stackWalkerClass, stackWalkerOptionClass));
stackWalkerWalkBuilder = lookup.findVirtual(stackWalkerClass, "walk", MethodType.methodType(Object.class, java.util.function.Function.class));
stackWalkerGetInstanceBuilder = stackWalkerClass.getMethod("getInstance", stackWalkerOptionClass);
stackWalkerWalkBuilder = stackWalkerClass.getMethod("walk", java.util.function.Function.class);
Class<?> stackframe = Class.forName("java.lang.StackWalker$StackFrame");
MethodHandle stackFrameGetDeclaringClass = lookup.findVirtual(stackframe, "getDeclaringClass", MethodType.methodType(Class.class));
Method stackFrameGetDeclaringClass = stackframe.getMethod("getDeclaringClass");
stackWalkerFilterBuilder = new java.util.function.Function<Stream<Object>, Class<?>>() {
@Override
public Class<?> apply(Stream<Object> t) {
Expand All @@ -306,13 +302,12 @@ public Class<?> apply(Stream<Object> t) {
stackWalkerWalk = stackWalkerWalkBuilder;
stackWalkerFilter = stackWalkerFilterBuilder;

MethodHandle securityManagerExposerConstructorBuilder;
MethodHandle securityManagerGetClassContextBuilder;
Constructor<?> securityManagerExposerConstructorBuilder;
Method securityManagerGetClassContextBuilder;
try {
Lookup lookup = MethodHandles.lookup();
Class<?> securityManagerExposerClass = Class.forName("com.sun.jna.SecurityManagerExposer");
securityManagerExposerConstructorBuilder = lookup.findConstructor(securityManagerExposerClass, MethodType.methodType(void.class));
securityManagerGetClassContextBuilder = lookup.findVirtual(securityManagerExposerClass, "getClassContext", MethodType.methodType(Class[].class));
securityManagerExposerConstructorBuilder = securityManagerExposerClass.getDeclaredConstructor();
securityManagerGetClassContextBuilder = securityManagerExposerClass.getDeclaredMethod("getClassContext");
} catch (Throwable ex) {
LOG.log(Level.FINE, "Failed to initialize stack accessor method SecurityManager", ex);
securityManagerExposerConstructorBuilder = null;
Expand All @@ -321,11 +316,10 @@ public Class<?> apply(Stream<Object> t) {
securityManagerExposerConstructor = securityManagerExposerConstructorBuilder;
securityManagerGetClassContext = securityManagerGetClassContextBuilder;

MethodHandle accessControllerDoPrivilegedBuilder = null;
Method accessControllerDoPrivilegedBuilder = null;
try {
Lookup lookup = MethodHandles.lookup();
Class<?> accessControllerClass = Class.forName("java.security.AccessController");
accessControllerDoPrivilegedBuilder = lookup.findStatic(accessControllerClass, "doPrivileged", MethodType.methodType(Object.class, PrivilegedAction.class));
accessControllerDoPrivilegedBuilder = accessControllerClass.getMethod("doPrivileged", PrivilegedAction.class);
} catch (Throwable ex) {
LOG.log(Level.FINE, "Failed to initialize AccessController#doPrivileged", ex);
accessControllerDoPrivilegedBuilder = null;
Expand Down Expand Up @@ -1352,7 +1346,7 @@ public static String getWebStartLibraryPath(final String libName) {
try {

final ClassLoader cl = Native.class.getClassLoader();
Method m = (Method) accessControllerDoPrivileged.invoke(new PrivilegedAction<Method>() {
Method m = (Method) accessControllerDoPrivileged.invoke(null, new PrivilegedAction<Method>() {
@Override
public Method run() {
try {
Expand Down Expand Up @@ -1624,7 +1618,7 @@ static Class<?> getCallingClass() {
// 3. Stackframe: method of outer caller
if (stackWalkerGetInstance != null) {
try {
Object walker = stackWalkerGetInstance.invoke(stackWalkerRetainClassReference);
Object walker = stackWalkerGetInstance.invoke(null, stackWalkerRetainClassReference);
Class<?> caller = (Class<?>) stackWalkerWalk.invoke(walker, stackWalkerFilter);
return caller;
} catch (Throwable ex) {
Expand All @@ -1635,7 +1629,7 @@ static Class<?> getCallingClass() {
if (securityManagerExposerConstructor != null) {
Class<?>[] context = null;
try {
Object securityManagerExposer = securityManagerExposerConstructor.invoke();
Object securityManagerExposer = securityManagerExposerConstructor.newInstance();
context = (Class<?>[]) securityManagerGetClassContext.invoke(securityManagerExposer);
} catch (Throwable ex) {
LOG.log(Level.WARNING, "Failed to invoke SecurityManagerExposer#<init> or SecurityManagerExposer#getClassContext", ex);
Expand Down
Loading