2017-12-19 2 views
0

Ein Projekt, das noch Java 6 unterstützt. Der folgende Code befindet sich in einer JAR-Datei, die mit Compiler-Kompatibilität erstellt wurde Stufe 1.6kann nicht auf ein Member der Klasse java.nio.DirectByteBuffer (in Modul java.base) mit Modifikatoren "public" zugreifen

Diese JAR-Datei sollte von Java-Anwendungen für Java 6 oder neuer erstellt werden. Es läuft auch gut in Java 8.

Jetzt mit Java9, bekomme ich Probleme mit nio.DirectByteBuffer, und ich versuchte, es auf diese Weise zu lösen, Reflexion mit:

@SuppressWarnings("unchecked") 
static void cleanDirectBuffer(sun.nio.ch.DirectBuffer buffer) { 
    if (JAVA_VERSION < 1.9) { 
     sun.misc.Cleaner cleaner = buffer.cleaner(); 
     if (cleaner != null) cleaner.clean(); 
    } else { 
     // For java9 do it the reflection way 
     @SuppressWarnings("rawtypes") 
     Class B = buffer.getClass(); 
     // will be a java.nio.DirectBuffer, which is unknown if compiled in 1.6 compliance mode 
     try { 
      java.lang.reflect.Method CleanerMethod = B.getMethod("cleaner"); 
      CleanerMethod.setAccessible(true); // fails here ! 
      Object cleaner = CleanerMethod.invoke(buffer); 
      if (cleaner == null) return; 
      @SuppressWarnings("rawtypes") 
      Class C = cleaner.getClass(); 
      java.lang.reflect.Method CleanMethod = C.getMethod("clean"); 
      CleanMethod.invoke(cleaner); 
     } catch (IllegalAccessException e) { 
      e.printStackTrace(); 
     } catch (Exception other) { 
      other.printStackTrace(); 
     } 
    } 
} 

Die JAVA_VERSION Erkennung ist in Ordnung und schaltet gut, abhängig von der Version meiner Berufung Code verwendet. jre6 zu jre8 Umgebungen verwenden schön den sun.misc.Cleaner Pfad, aber das funktioniert nicht in java9

Sie werden wahrscheinlich feststellen, dass ich kein Experte in java.reflection bin. durch Erraten, fand ich .setAccessible(true);

und Antwort Lanze-java (dank bisher) half ein wenig:

Version2:

Class B = buffer.getClass(); 
    try { 
     java.lang.reflect.Method CleanerMethod = B.getDeclaredMethod("cleaner"); 
     CleanerMethod.setAccessible(true); 
     Object cleaner = CleanerMethod.invoke(buffer); 
     if (cleaner == null) return; 
     @SuppressWarnings("rawtypes") 
     Class C = cleaner.getClass(); 
     java.lang.reflect.Method CleanMethod = C.getDeclaredMethod("clean"); 
     CleanMethod.setAccessible(true); // Now it fails here ! 
     CleanMethod.invoke(cleaner); 
    } catch (InaccessibleObjectException e) { 
     // ** causes: Unable to make public void jdk.internal.ref.Cleaner.clean() accessible: module java.base does not "exports jdk.internal.ref" to unnamed module ** 
    } 

Zusätzlich wird die Warnung mit dem ersten CleanerMethod.setAccessible(true)

WARNING: An illegal reflective access operation has occurred 
WARNING: Illegal reflective access by my.package.MyClass (file:/xyz.jar) to method java.nio.DirectByteBuffer.cleaner() 
... 
WARNING: All illegal access operations will be denied in a future release 

... klingt nicht zu gesund? Aber ach, es ist nur eine Warnung :)

Was fehlt mir noch, oder gibt es einen anderen/besseren Ansatz für mein Problem?

Antwort

0

Class.getMethod() und Class.getField() usw. geben nur die öffentlichen Methoden/Felder zurück. Ich denke du willst Class.getDeclaredMethod().

+0

aber die Methode cleaner() "ist" öffentlich? – datafiddler

Verwandte Themen