JNI EnsureLocalCapacity - WARUM?

9

Sehen Sie sich die JNI-Dokumentation hier an: Ссылка

Sehen Sie sich genauer an, was in der Beschreibung der EnsureLocalCapacity-Funktion gesagt wird:

  

Aus Gründen der Abwärtskompatibilität weist die VM darüber hinaus lokale Referenzen zu   die gesicherte Kapazität. (Als Debugging - Unterstützung kann die VM den   Benutzerwarnungen, dass zu viele lokale Referenzen erstellt werden. In dem   JDK kann der Programmierer die Befehlszeilenoption -verbose: jni zur Verfügung stellen   Schalten Sie diese Nachrichten ein.) Die VM ruft FatalError auf, wenn sie nicht mehr lokal ist   Referenzen können über die gesicherte Kapazität hinaus erstellt werden.

Und darüber hinaus, wie PushLocalFrame ein "Kapazität" -Argument nimmt. (Und übrigens nicht erwähnt, ob dies eine harte Grenze oder eine weiche Grenze wie bei EnsureLocalCapacity ist).

Woher kommt der ganze Unsinn über die lokale Referenzkapazität? Die Dokumentation sagt, dass VM bereit sein wird, Referenzen über die aktuelle formale Kapazität hinaus zuzuordnen. Warum also nicht einfach so und die ganze Kapazität aus der API streichen?

Um eine Analogie zu C zu geben, fühlt es sich an, als ob ich gefragt werde, wie viele malloc () -Aufrufe ich vorhabe, und es fühlt sich ein bisschen lächerlich an.

Gibt es etwas Wichtiges, das ich hier nicht sehe?

    
patrick-rutkowski 16.08.2011, 16:51
quelle

3 Antworten

0

Das ist meine Vermutung . Ich vermute, dass die wachsende lokale Referenzkapazität teuer ist und diese Funktion ermöglicht, die gewünschte Kapazität einmal pro nativem Methodenaufruf anzufordern. Ich denke, es geht mehr um Leistung als um Korrektheit.

    
18446744073709551615 28.02.2012 10:32
quelle
0

Nach meinem Verständnis ist die lokale Referenztabellengröße vordefiniert, und wenn Sie mehr als diese zuweisen, stürzt sie einfach ab. Es ist also nicht so, dass VM dir mehr lokale Refs für immer geben wird. Ich habe dies oft während der Arbeit mit JNI auf Android erlebt. Es ist oft schwierig, ein solches Speicherleck zu finden. Und das Aufrufen von env- & gt; DeleteLocalRef () jedes Mal, wenn Sie etwas mit JNI-lokalen Referenzen tun, überlagert nur den Code. Anstatt den Code mit DeleteLocalRef () Aufrufen zu überlisten, können wir einfach sicherstellen, dass wir nicht zu viele Referenzen erstellen und den Code sauber halten. Und selbst wenn wir viel mehr lokale Referenzen zuweisen möchten, können wir einfach PushLocalFrame () / PopLocalFrame () aufrufen und viele Aufrufe von DeleteLocalRef () vermeiden.

Um Ihnen eine Analogie zu "C" zu geben, werden Sie gebeten, Ihre Calls für malloc vorzuplanen, um alle notwendigen Aufrufe von free () am Ende zu vermeiden.

    
Tomasz Jarosik 31.01.2016 12:48
quelle
0

Die JNI-Dokumentation ist zu diesem Thema matschig. Ich habe in der Praxis festgestellt, dass die Anzahl der lokalen Referenzen manchmal unbegrenzt ist, aber Sie können wirklich keine lokalen Referenzen mehr haben, zum Beispiel beim Iterieren über ein Array mit JNI-Aufrufen. Was ist eine lokale Referenz? Es handelt sich um ein Job-Objekt (oder jarray, jstring usw.), das Sie aus einer dieser Quellen erhalten:

  • Wurde von einem Raw-JNI-Aufruf wie NewObjectV () oder GetObjectArrayElement ()
  • zurückgegeben
  • Von einem Methodenaufruf wie CallObjectMethodV ()
  • zurückgegeben
  • Wurde als Argument an Ihre native Funktion übergeben
  • Wahrscheinlich habe ich andere vergessen

Davon müssen Sie sich in der Regel keine Gedanken über die Referenzen machen, die Ihnen in einem Methodenargument übergeben werden, AUSSER wenn Sie beabsichtigen, den Verweis über den aktuellen Methodenaufruf hinaus beizubehalten. In diesem Fall sollten Sie ihn in global konvertieren.

Es ist erwähnenswert, dass Sie sich nicht an eine lokale Referenz außerhalb des aktuellen Methodenbereichs halten müssen. Wenn Sie es in einem C ++ - Objekt speichern möchten, müssen Sie es in global konvertieren. Lokale Referenzen haben zwei Vorteile

  1. Sie werden immer automatisch freigegeben, wenn der aktuelle Frame den Gültigkeitsbereich verlässt.
  2. Sie sind schneller als die Konvertierung in global

Wie bei den meisten JNI-Fehlern ist jeder Missbrauch von Referenzen schrecklich zu diagnostizieren, also wollen Sie wirklich keinen bekommen. Ihre beste Verteidigung ist ein konsequenter Ansatz. Nach meiner Erfahrung sind die Kosten für die Umstellung von lokal auf global ziemlich gering. Ich würde folgendes vorschlagen, es sei denn, Sie haben sehr strenge Leistungsanforderungen.
In Anbetracht dessen lautet meine Regel: IMMER lokale Refs in globale Refs umwandeln, indem Code wie folgt verwendet wird:

%Vor%

An diesem Punkt können Sie wissen, dass jeder Verweis global ist, und wenn Sie fertig sind, müssen Sie daran denken, env- & gt; DeleteGlobalRef (globaljo) auf jedem zu machen. In C ++ ist es möglich, eine Wrapper-Klasse um JNI-Referenzen zu schreiben, die env- & gt; DeleteGlobalRef () im dtor aufruft. Da JNI jedoch nicht auf die JNI-Referenzen für Sie verweist, müssen Sie diese möglicherweise ebenfalls erstellen.

    
Wheezil 01.03.2017 13:42
quelle

Tags und Links