Skip to content

Commit cbfcb4a

Browse files
Merge pull request #1731 from matthiasblaesing/ancient_android
Restore support for Android versions not supporting MethodHandles
2 parents 699935f + 4ba086b commit cbfcb4a

3 files changed

Lines changed: 24 additions & 33 deletions

File tree

CHANGES.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,12 @@ NOTE: as of JNA 4.0, JNA is now dual-licensed under LGPL and AL 2.0 (see LICENSE
22

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

5-
Next Release (5.20.0)
5+
Next Release (5.19.1)
66
=====================
77

8-
Features
9-
--------
10-
118
Bug Fixes
129
---------
13-
10+
* [#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).
1411

1512
Release 5.19.0
1613
==============

common.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
<!-- JNA library release version - android versionCode is derived from mjar/minor/revision -->
1010
<property name="jna.major" value="5"/>
11-
<property name="jna.minor" value="20"/>
12-
<property name="jna.revision" value="0"/>
11+
<property name="jna.minor" value="19"/>
12+
<property name="jna.revision" value="1"/>
1313
<property name="jna.build" value="0"/> <!--${build.number}-->
1414
<condition property="version.suffix" value="" else="-SNAPSHOT">
1515
<or>

src/com/sun/jna/Native.java

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,10 @@
3535
import java.io.IOException;
3636
import java.io.InputStream;
3737
import java.io.UnsupportedEncodingException;
38-
import java.lang.invoke.MethodHandle;
39-
import java.lang.invoke.MethodHandles;
40-
import java.lang.invoke.MethodHandles.Lookup;
41-
import java.lang.invoke.MethodType;
4238
import java.lang.ref.Reference;
4339
import java.lang.ref.WeakReference;
4440
import java.lang.reflect.Array;
41+
import java.lang.reflect.Constructor;
4542
import java.lang.reflect.Field;
4643
import java.lang.reflect.InvocationHandler;
4744
import java.lang.reflect.Method;
@@ -184,15 +181,15 @@ public void uncaughtException(Callback c, Throwable e) {
184181
private static final int TYPE_BOOL = 4;
185182
private static final int TYPE_LONG_DOUBLE = 5;
186183

187-
private static final MethodHandle stackWalkerGetInstance;
184+
private static final Method stackWalkerGetInstance;
188185
private static final Enum stackWalkerRetainClassReference;
189-
private static final MethodHandle stackWalkerWalk;
186+
private static final Method stackWalkerWalk;
190187
private static final Object stackWalkerFilter;
191188

192-
private static final MethodHandle securityManagerExposerConstructor;
193-
private static final MethodHandle securityManagerGetClassContext;
189+
private static final Constructor securityManagerExposerConstructor;
190+
private static final Method securityManagerGetClassContext;
194191

195-
private static final MethodHandle accessControllerDoPrivileged;
192+
private static final Method accessControllerDoPrivileged;
196193

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

272269
Enum stackWalkerRetainClassReferenceBuilder;
273-
MethodHandle stackWalkerGetInstanceBuilder;
274-
MethodHandle stackWalkerWalkBuilder;
270+
Method stackWalkerGetInstanceBuilder;
271+
Method stackWalkerWalkBuilder;
275272
Object stackWalkerFilterBuilder;
276273
try {
277-
Lookup lookup = MethodHandles.lookup();
278274
Class<?> stackWalkerClass = Class.forName("java.lang.StackWalker");
279275
Class<? extends Enum> stackWalkerOptionClass = (Class<? extends Enum>) Class.forName("java.lang.StackWalker$Option");
280276
stackWalkerRetainClassReferenceBuilder = Enum.valueOf(stackWalkerOptionClass, "RETAIN_CLASS_REFERENCE");
281-
stackWalkerGetInstanceBuilder = lookup.findStatic(stackWalkerClass, "getInstance", MethodType.methodType(stackWalkerClass, stackWalkerOptionClass));
282-
stackWalkerWalkBuilder = lookup.findVirtual(stackWalkerClass, "walk", MethodType.methodType(Object.class, java.util.function.Function.class));
277+
stackWalkerGetInstanceBuilder = stackWalkerClass.getMethod("getInstance", stackWalkerOptionClass);
278+
stackWalkerWalkBuilder = stackWalkerClass.getMethod("walk", java.util.function.Function.class);
283279
Class<?> stackframe = Class.forName("java.lang.StackWalker$StackFrame");
284-
MethodHandle stackFrameGetDeclaringClass = lookup.findVirtual(stackframe, "getDeclaringClass", MethodType.methodType(Class.class));
280+
Method stackFrameGetDeclaringClass = stackframe.getMethod("getDeclaringClass");
285281
stackWalkerFilterBuilder = new java.util.function.Function<Stream<Object>, Class<?>>() {
286282
@Override
287283
public Class<?> apply(Stream<Object> t) {
@@ -306,13 +302,12 @@ public Class<?> apply(Stream<Object> t) {
306302
stackWalkerWalk = stackWalkerWalkBuilder;
307303
stackWalkerFilter = stackWalkerFilterBuilder;
308304

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

324-
MethodHandle accessControllerDoPrivilegedBuilder = null;
319+
Method accessControllerDoPrivilegedBuilder = null;
325320
try {
326-
Lookup lookup = MethodHandles.lookup();
327321
Class<?> accessControllerClass = Class.forName("java.security.AccessController");
328-
accessControllerDoPrivilegedBuilder = lookup.findStatic(accessControllerClass, "doPrivileged", MethodType.methodType(Object.class, PrivilegedAction.class));
322+
accessControllerDoPrivilegedBuilder = accessControllerClass.getMethod("doPrivileged", PrivilegedAction.class);
329323
} catch (Throwable ex) {
330324
LOG.log(Level.FINE, "Failed to initialize AccessController#doPrivileged", ex);
331325
accessControllerDoPrivilegedBuilder = null;
@@ -1352,7 +1346,7 @@ public static String getWebStartLibraryPath(final String libName) {
13521346
try {
13531347

13541348
final ClassLoader cl = Native.class.getClassLoader();
1355-
Method m = (Method) accessControllerDoPrivileged.invoke(new PrivilegedAction<Method>() {
1349+
Method m = (Method) accessControllerDoPrivileged.invoke(null, new PrivilegedAction<Method>() {
13561350
@Override
13571351
public Method run() {
13581352
try {
@@ -1624,7 +1618,7 @@ static Class<?> getCallingClass() {
16241618
// 3. Stackframe: method of outer caller
16251619
if (stackWalkerGetInstance != null) {
16261620
try {
1627-
Object walker = stackWalkerGetInstance.invoke(stackWalkerRetainClassReference);
1621+
Object walker = stackWalkerGetInstance.invoke(null, stackWalkerRetainClassReference);
16281622
Class<?> caller = (Class<?>) stackWalkerWalk.invoke(walker, stackWalkerFilter);
16291623
return caller;
16301624
} catch (Throwable ex) {
@@ -1635,7 +1629,7 @@ static Class<?> getCallingClass() {
16351629
if (securityManagerExposerConstructor != null) {
16361630
Class<?>[] context = null;
16371631
try {
1638-
Object securityManagerExposer = securityManagerExposerConstructor.invoke();
1632+
Object securityManagerExposer = securityManagerExposerConstructor.newInstance();
16391633
context = (Class<?>[]) securityManagerGetClassContext.invoke(securityManagerExposer);
16401634
} catch (Throwable ex) {
16411635
LOG.log(Level.WARNING, "Failed to invoke SecurityManagerExposer#<init> or SecurityManagerExposer#getClassContext", ex);

0 commit comments

Comments
 (0)