Copia e blocco
La raccolta dati inutilizzati potrebbe, in qualsiasi momento, decidere di compattare l'heap raccolto dai dati inutilizzati. La compattazione implica lo spostamento fisico di oggetti da un indirizzo all'altro. Questi oggetti potrebbero essere indicati da un riferimento locale o globale JNI. Per consentire la compattazione in modo sicuro, i riferimenti JNI non sono puntatori diretti all'heap. Almeno un livello di riferimento indiretto isola il codice nativo dallo spostamento degli oggetti.
Se un metodo nativo deve ottenere l'indirizzabilità diretta all'interno di un oggetto, la situazione è più complicata. Il requisito di indirizzare direttamente, o bloccare, l'heap è tipico quando è necessario un accesso rapido e condiviso a array primitivi di grandi dimensioni. Un esempio potrebbe includere un buffer dello schermo. In questi casi, è possibile utilizzare una sezione critica JNI, che impone ulteriori requisiti al programmatore, come specificato nella descrizione JNI per queste funzioni. Consultare la specifica JNI per i dettagli.
- GetPrimitiveArrayCritical restituisce l'indirizzo heap diretto di un array Java™ , disabilitando la raccolta dati inutilizzati fino a quando non viene richiamato il ReleasePrimitiveArrayCritical corrispondente.
- GetStringCritical restituisce l'indirizzo heap diretto di un'istanza java.lang.String , disabilitando la raccolta dati inutilizzati fino a quando non viene richiamato ReleaseStringCritical .
Tutte le altre interfacce Get<PrimitiveType>ArrayElements restituiscono una copia non influenzata dalla compattazione.
Quando si utilizza la politica di raccolta dati inutilizzati bilanciata, i moduli *Critical delle chiamate potrebbero non restituire un puntatore diretto nell'heap, che si riflette nell'indicatore isCopy . Questo comportamento è dovuto ad una rappresentazione interna di array più grandi, dove i dati potrebbero non essere sequenziali. Generalmente, un array con memoria inferiore a 1/1000th dell'heap viene restituito come puntatore diretto.
Utilizzo dell'indicatore isCopy
Le funzioni JNI Get<Type> specificano un parametro di uscita pass-by-reference (jboolean *isCopy ) che consente al chiamante di determinare se una determinata chiamata JNI restituisce l'indirizzo di una copia o l'indirizzo dell'oggetto appuntato nell'heap.
Le funzioni Get< Tipo> e Release< Tipo> sono disponibili a coppie:
- GetStringChars e ReleaseStringChars
- GetStringCritical e ReleaseStringCritical
- GetStringUTFChars e ReleaseStringUTFChars
- Get<PrimitiveType>ArrayElements e Release<PrimitiveType>ArrayElements
- GetPrimitiveArrayCritical e ReleasePrimitiveArrayCritical
Se si passa un indirizzo non null come parametro isCopy , la funzione JNI imposta il valore jboolean a tale indirizzo su JNI_TRUE se l'indirizzo restituito è l'indirizzo di una copia degli elementi dell'array e JNI_FALSE se l'indirizzo punta direttamente all'oggetto bloccato nell'heap.
Ad eccezione delle funzioni critiche, la VM J9 restituisce sempre una copia. La copia alleggerisce il carico sulla raccolta dati inutilizzati, perché gli oggetti bloccati non possono essere compattati e complicano la deframmentazione.
Per evitare perdite, è necessario:
- Gestire personalmente la memoria di copia utilizzando le funzioni Richiama< Tipo>Regione e Imposta< Tipo>Regione.
- Assicurarsi di liberare le copie effettuate da una funzione Get< Type> richiamando la funzione Release< Type> corrispondente quando la copia non è più necessaria.
Utilizzo dell'indicatore di modalità
Quando si chiama Release<Type>ArrayElements, l'ultimo parametro è un flag di modalità. L'indicatore di modalità viene utilizzato per evitare la copia non necessaria nell'heap Java quando si utilizza un array copiato. L'indicatore di modalità viene ignorato se si sta utilizzando un array che è stato bloccato.
È necessario richiamare il rilascio< Tipo> una volta per ogni chiamata Get< Tipo> , indipendentemente dal valore del parametro isCopy . Questa operazione è necessaria perché il richiamo del rilascio< Tipo> elimina i riferimenti locali JNI che altrimenti potrebbero impedire la raccolta dati inutilizzati.
- 0
- Aggiornare i dati sull'heap Java. Liberare lo spazio utilizzato dalla copia.
- COMMIT JNI_IT
- Aggiornare i dati sull'heap Java. Non liberare lo spazio utilizzato dalla copia.
- JNI_ABORT
- Non aggiornare i dati sull'heap Java. Liberare lo spazio utilizzato dalla copia.
L'indicatore di modalità '0' è la scelta più sicura per la chiamata Release< Tipo> . Se la copia dei dati è stata modificata o meno, l'heap viene aggiornato con la copia e non ci sono perdite.
Per evitare di dover copiare una copia non modificata, utilizzare il valore della modalità JNI_ABORT. Se si modifica l'array restituito, controllare l'indicatore isCopy prima di utilizzare il valore della modalità JNI_ABORT per eseguire il "rollback" delle modifiche. Questo passaggio è necessario perché una JVM di blocco lascia l'heap in uno stato diverso rispetto a una JVM di copia.
Un modo generico per utilizzare isCopy e gli indicatori di modalità
Di seguito viene riportato un modo generico per utilizzare gli indicatori isCopy e modalità. Funziona con tutte le JVM e garantisce che venga eseguito il commit delle modifiche e che non si verifichino perdite.
- non utilizzare l'indicatore isCopy . Passare null o 0.
- Impostare sempre l'indicatore di modalità su zero.
Un uso complicato di questi indicatori è necessario solo per l'ottimizzazione. Se si utilizza la modalità generica, è comunque necessario considerare la sincronizzazione. Vedere Sincronizzazione.