2015-11-26 23 views
5

Fondamentalmente capisco l'idea di codice gestito e nativo e il loro difference. Ma come è tecnicamente possibile per loro comunicare tra loro? Immagina il seguente esempio:Codice misto (nativo, gestito): come interagisce (tecnicamente)?

Ho una libreria C++ statica o dinamica che è compilata per una piattaforma specifica. Ora scrivo un programma Java. All'interno di questo codice chiamo le funzioni della libreria con la parola chiave 'nativa'. Costruisco un file jar con il bytecode e i file della libreria C++ rimarranno separati. Il risultato non sarà più indipendente dalla piattaforma.

  1. Ma come fa il programma java a sapere se esistono i metodi nativi chiamati?

  2. Come viene eseguito l'intero codice durante il runtime? So che il bytecode verrà interpretato o compilato con JIT.

  3. Come tutto questo si inserisce nel paradigma sandboxing? Il codice nativo viene eseguito anche all'interno della sandbox?

  4. Funziona perché sia ​​il codice (java e C++) sia il codice macchina alla fine?

Forse questa è una domanda stupida. Ma mi stavo sempre chiedendo ...

EDIT: Ho ricevuto 3 buone risposte. davvero non riesco a decidere quale mi ha aiutato di più. Ma segnerò questa domanda come risposta per chiudere questo argomento dalla mia parte.

risposta

2
  1. Non sa fino a quando non si chiama il metodo. Il codice nativo risiede in un file .DLL o .so; java runtime ricerca specifici punti di ingresso che corrispondono ai metodi nativi che hai creato (se stai usando JNI, c'è uno strumento in grado di analizzare i metodi e creare stub di funzioni che daranno luogo a tali punti di ingresso una volta compilati). Se il punto di ingresso desiderato non è presente, verrà generata un'eccezione.

  2. Il codice generato dal JIT non è del tutto autosufficiente; deve chiamare il codice nativo esterno (sia per le routine di runtime di basso livello che per i servizi del sistema operativo) di volta in volta. Lo stesso meccanismo è usato per invocare il codice per i tuoi metodi nativi.

  3. No. Puoi fare tutto ciò che faresti in un puro programma C/C++. Le uniche cose che impediranno di fare qualsiasi danno sono le misure di sicurezza esterne che hai (restrizioni dei privilegi di accesso, altre protezioni del sistema operativo, software di sicurezza, ecc.) Ma la VM non ti proteggerà.

  4. No, JNI esisteva ancora prima che comparisse la JIT. Il meccanismo è lo stesso, se il bytecode viene eseguito da un interprete e vuoi che questo interprete invochi il codice nativo, hai solo bisogno di una logica per determinare che un dato metodo è "esterno" e dovrebbe essere chiamato come codice nativo . Questa informazione è contenuta nel file .class compilato, e quando l'interprete o JIT lo carica, crea una rappresentazione della memoria che rende facile indirizzare la chiamata su una ricerca di metodo.

1

Dipende dalla piattaforma. Su Linux, Solaris, ecc., JRE utilizza dlopen. Su Windows, utilizza LoadLibraryEx e GetProcAddress. Se JRE è in esecuzione in modalità interpretata, chiama quella funzione; in modalità compilata, compila codice bytecode Java in codice nativo che chiama tale funzione.

Su tutti i JRE che conosco, non è possibile chiamare direttamente una funzione nativa in una libreria statica; solo uno in una libreria dinamica.

Il codice nativo non deve essere limitato a una singola piattaforma; se è C standard, puoi probabilmente compilarlo con un cross-compiler per ogni piattaforma su cui è disponibile un JRE.

1
  1. La JVM controllerà le librerie definite e vedere se il metodo è lì

  2. Bytecode saranno interpretati o JITted e si aggiunge una chiamata al codice nativo. Questo può includere valori di boxing/deboxing e altre cose necessarie per convertire i dati in formato adatto. Le librerie hanno una determinata interfaccia che viene spiegata al compilatore Java e produrrà la logica dell'interfaccia richiesta.

  3. Dipende dalla sandbox. Per impostazione predefinita, il codice nativo è il codice nativo. Non chiama le API Java, quindi la JVM non può governarlo in alcun modo. Ma potrebbero esserci altre limitazioni, ad esempio la JVM potrebbe eseguire il codice nativo con librerie che forniscono sandboxing, oppure il sistema operativo potrebbe avere un modo di sandboxing.

  4. Dipende da cosa intendi. Alla fine qualsiasi cosa faccia il computer è un codice macchina, ma in questo caso non ha molta importanza. Ciò che conta è la parte di traduzione e esecuzione. Questa è la colla che fa funzionare tutto.

Pensare al sistema come a persone. La persona A parla solo giapponese, ma vuole prenotare un hotel a Parigi. L'addetto alla reception B parla solo francese. La persona A può ottenere un traduttore che tradurrà i suoi comandi in francese, l'addetto alla reception di comando B e in cambio tradurrà ciò che B ha prodotto in una persona di forma A capisce. Questa è la parte JNI.