23
23
*/
24
24
package com .sun .jna ;
25
25
26
+ import com .sun .jna .Callback .UncaughtExceptionHandler ;
27
+ import com .sun .jna .Structure .FFIType ;
26
28
import java .awt .Component ;
27
29
import java .awt .GraphicsEnvironment ;
28
30
import java .awt .HeadlessException ;
33
35
import java .io .IOException ;
34
36
import java .io .InputStream ;
35
37
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 ;
36
42
import java .lang .ref .Reference ;
37
43
import java .lang .ref .WeakReference ;
38
44
import java .lang .reflect .Array ;
50
56
import java .nio .charset .Charset ;
51
57
import java .nio .charset .IllegalCharsetNameException ;
52
58
import java .nio .charset .UnsupportedCharsetException ;
53
- import java .security .AccessController ;
54
59
import java .security .PrivilegedAction ;
55
60
import java .util .ArrayList ;
56
61
import java .util .Arrays ;
60
65
import java .util .Map ;
61
66
import java .util .StringTokenizer ;
62
67
import java .util .WeakHashMap ;
63
-
64
- import com .sun .jna .Callback .UncaughtExceptionHandler ;
65
- import com .sun .jna .Structure .FFIType ;
66
68
import java .util .logging .Level ;
67
69
import java .util .logging .Logger ;
70
+ import java .util .stream .Stream ;
68
71
69
72
/** Provides generation of invocation plumbing for a defined native
70
73
* library interface. Also provides various utilities for native operations.
@@ -181,6 +184,16 @@ public void uncaughtException(Callback c, Throwable e) {
181
184
private static final int TYPE_BOOL = 4 ;
182
185
private static final int TYPE_LONG_DOUBLE = 5 ;
183
186
187
+ private static final MethodHandle stackWalkerGetInstance ;
188
+ private static final Enum stackWalkerRetainClassReference ;
189
+ private static final MethodHandle stackWalkerWalk ;
190
+ private static final Object stackWalkerFilter ;
191
+
192
+ private static final MethodHandle securityManagerExposerConstructor ;
193
+ private static final MethodHandle securityManagerGetClassContext ;
194
+
195
+ private static final MethodHandle accessControllerDoPrivileged ;
196
+
184
197
static final int MAX_ALIGNMENT ;
185
198
static final int MAX_PADDING ;
186
199
@@ -255,6 +268,70 @@ static boolean isCompatibleVersion(String expectedVersion, String nativeVersion)
255
268
|| (Platform .isAndroid () && !Platform .isIntel ())
256
269
? 8 : LONG_SIZE ;
257
270
MAX_PADDING = (Platform .isMac () && Platform .isPPC ()) ? 8 : MAX_ALIGNMENT ;
271
+
272
+ Enum stackWalkerRetainClassReferenceBuilder ;
273
+ MethodHandle stackWalkerGetInstanceBuilder ;
274
+ MethodHandle stackWalkerWalkBuilder ;
275
+ Object stackWalkerFilterBuilder ;
276
+ try {
277
+ Lookup lookup = MethodHandles .lookup ();
278
+ Class <?> stackWalkerClass = Class .forName ("java.lang.StackWalker" );
279
+ Class <? extends Enum > stackWalkerOptionClass = (Class <? extends Enum >) Class .forName ("java.lang.StackWalker$Option" );
280
+ 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 ));
283
+ Class <?> stackframe = Class .forName ("java.lang.StackWalker$StackFrame" );
284
+ MethodHandle stackFrameGetDeclaringClass = lookup .findVirtual (stackframe , "getDeclaringClass" , MethodType .methodType (Class .class ));
285
+ stackWalkerFilterBuilder = new java .util .function .Function <Stream <Object >, Class <?>>() {
286
+ @ Override
287
+ public Class <?> apply (Stream <Object > t ) {
288
+ Object stackFrame = t .skip (2 ).findFirst ().get ();
289
+ try {
290
+ return (Class <?>) stackFrameGetDeclaringClass .invoke (stackFrame );
291
+ } catch (Throwable ex ) {
292
+ return null ;
293
+ }
294
+ }
295
+ };
296
+
297
+ } catch (Throwable ex ) {
298
+ LOG .log (Level .FINE , "Failed to initialize stack accessor method StackWalker" , ex );
299
+ stackWalkerRetainClassReferenceBuilder = null ;
300
+ stackWalkerGetInstanceBuilder = null ;
301
+ stackWalkerWalkBuilder = null ;
302
+ stackWalkerFilterBuilder = null ;
303
+ }
304
+ stackWalkerRetainClassReference = stackWalkerRetainClassReferenceBuilder ;
305
+ stackWalkerGetInstance = stackWalkerGetInstanceBuilder ;
306
+ stackWalkerWalk = stackWalkerWalkBuilder ;
307
+ stackWalkerFilter = stackWalkerFilterBuilder ;
308
+
309
+ MethodHandle securityManagerExposerConstructorBuilder ;
310
+ MethodHandle securityManagerGetClassContextBuilder ;
311
+ try {
312
+ Lookup lookup = MethodHandles .lookup ();
313
+ 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 ));
316
+ } catch (Throwable ex ) {
317
+ LOG .log (Level .FINE , "Failed to initialize stack accessor method SecurityManager" , ex );
318
+ securityManagerExposerConstructorBuilder = null ;
319
+ securityManagerGetClassContextBuilder = null ;
320
+ }
321
+ securityManagerExposerConstructor = securityManagerExposerConstructorBuilder ;
322
+ securityManagerGetClassContext = securityManagerGetClassContextBuilder ;
323
+
324
+ MethodHandle accessControllerDoPrivilegedBuilder = null ;
325
+ try {
326
+ Lookup lookup = MethodHandles .lookup ();
327
+ Class <?> accessControllerClass = Class .forName ("java.security.AccessController" );
328
+ accessControllerDoPrivilegedBuilder = lookup .findStatic (accessControllerClass , "doPrivileged" , MethodType .methodType (Object .class , PrivilegedAction .class ));
329
+ } catch (Throwable ex ) {
330
+ LOG .log (Level .FINE , "Failed to initialize AccessController#doPrivileged" , ex );
331
+ accessControllerDoPrivilegedBuilder = null ;
332
+ }
333
+ accessControllerDoPrivileged = accessControllerDoPrivilegedBuilder ;
334
+
258
335
System .setProperty ("jna.loaded" , "true" );
259
336
}
260
337
@@ -1275,7 +1352,7 @@ public static String getWebStartLibraryPath(final String libName) {
1275
1352
try {
1276
1353
1277
1354
final ClassLoader cl = Native .class .getClassLoader ();
1278
- Method m = AccessController . doPrivileged (new PrivilegedAction <Method >() {
1355
+ Method m = ( Method ) accessControllerDoPrivileged . invoke (new PrivilegedAction <Method >() {
1279
1356
@ Override
1280
1357
public Method run () {
1281
1358
try {
@@ -1294,7 +1371,7 @@ public Method run() {
1294
1371
}
1295
1372
return null ;
1296
1373
}
1297
- catch (Exception e ) {
1374
+ catch (Throwable e ) {
1298
1375
return null ;
1299
1376
}
1300
1377
}
@@ -1523,19 +1600,35 @@ static Class<?> findDirectMappedClass(Class<?> cls) {
1523
1600
was made.
1524
1601
*/
1525
1602
static Class <?> getCallingClass () {
1526
- Class <?>[] context = new SecurityManager () {
1527
- @ Override
1528
- public Class <?>[] getClassContext () {
1529
- return super .getClassContext ();
1603
+ if (stackWalkerGetInstance != null ) {
1604
+ try {
1605
+ Object walker = stackWalkerGetInstance .invoke (stackWalkerRetainClassReference );
1606
+ Class <?> caller = (Class <?>) stackWalkerWalk .invoke (walker , stackWalkerFilter );
1607
+ return caller ;
1608
+ } catch (Throwable ex ) {
1609
+ LOG .log (Level .WARNING , "Failed to invoke StackWalker#getInstance or StackWalker#walk" , ex );
1530
1610
}
1531
- }.getClassContext ();
1532
- if (context == null ) {
1533
- throw new IllegalStateException ("The SecurityManager implementation on this platform is broken; you must explicitly provide the class to register" );
1534
1611
}
1535
- if (context .length < 4 ) {
1536
- throw new IllegalStateException ("This method must be called from the static initializer of a class" );
1612
+
1613
+ if (securityManagerExposerConstructor != null ) {
1614
+ Class <?>[] context = null ;
1615
+ try {
1616
+ Object securityManagerExposer = securityManagerExposerConstructor .invoke ();
1617
+ context = (Class <?>[]) securityManagerGetClassContext .invoke (securityManagerExposer );
1618
+ } catch (Throwable ex ) {
1619
+ LOG .log (Level .WARNING , "Failed to invoke SecurityManagerExposer#<init> or SecurityManagerExposer#getClassContext" , ex );
1620
+ }
1621
+
1622
+ if (context == null ) {
1623
+ throw new IllegalStateException ("The SecurityManager implementation on this platform is broken; you must explicitly provide the class to register" );
1624
+ }
1625
+ if (context .length < 4 ) {
1626
+ throw new IllegalStateException ("This method must be called from the static initializer of a class" );
1627
+ }
1628
+ return context [3 ];
1537
1629
}
1538
- return context [3 ];
1630
+
1631
+ throw new IllegalStateException ("Neither the StackWalker, nor the SecurityManager based getCallingClass implementation are useable; you must explicitly provide the class to register" );
1539
1632
}
1540
1633
1541
1634
/**
0 commit comments