Ho usato JNI ora e poi sia in applicazioni standard (desktop) Java che in applicazioni Android. Ecco il succo di tutto questo:
1. La tua domanda chiede in particolare se le prestazioni sono migliorate da JNI: principalmente, no. Ci sono alcune poche e specifiche situazioni in cui le prestazioni sono migliorate. Il 98,3% delle volte questo non sarà il caso.
Inoltre, l'aggiunta di JNI esclusivamente per i vantaggi in termini di prestazioni complicherà notevolmente il progetto (rispetto alla semplice scrittura in Java o C / C ++):
Esistono moltissimi strumenti molto validi (IDE, strumenti di gestione del progetto, librerie, strumenti di test, ecc.) Per progetti solo Java (come per progetti C e / o C ++ -only). Tuttavia ci sono molti meno strumenti (e, IMHO, di qualità inferiore) che consentono di gestire un progetto misto (Java) + (JNI) + (C e / o C ++) tutto in una volta. Molto spesso è necessario introdurre strumenti separati per la parte Java del progetto, un altro per la parte C / C ++ del progetto e magari eseguire un po 'di sviluppo di strumenti personalizzati (come script e simili) per le parti JNI .
Ecco un esempio: recentemente ho aiutato un amico con un progetto Java che utilizzava circa il 90% del suo codice usando BigDecimal e BigInteger classi. Il codice ha fatto molte delle operazioni algebriche comuni (e alcune delle più esotiche) con queste: + - / * ma anche log, radici quadrate e alcune che non ricordo più adesso. Abbiamo anche provato a sostituire quelle parti del codice con il codice JNI e C che utilizzava la libreria MPFR , dopo aver notato che le funzioni che stavamo usando dell'API BigXXX di Java erano presenti anche in questa libreria. Per farla breve, in questo caso particolare, il guadagno in termini di prestazioni è stato di circa 10-15 volte. Alla fine abbiamo deciso di implementare l'intero modulo in C e di utilizzare solo Java per l'interfaccia utente insieme alle chiamate JNI non granulari verso il nuovo modulo C.
2. Penso che la ragione principale per cui qualcuno dovrebbe usare JNI è se ha già molti codici C e / o C ++ complessi che devono essere integrati con il codice Java.
Un punto in cui questo può essere applicato è quando si trasferisce un videogioco esistente sulla piattaforma Android: la maggior parte dei giochi è realizzata in C / C ++. Android, mentre al suo core gira su un kernel Linux e si occupa del codice C / C ++, offre infatti un'API Java (un ambiente di sviluppo Java molto simile al JDK / JVM che si ottiene sul PC / Mac). In un tale contesto, fare un sottile wrapper Java attorno al codice C ++ esistente per ottenere un vecchio gioco attivo su Android è molto più veloce della conversione completa di tutto il codice C / C ++ in Java. Con l'approache Java thin wrapper c'è una perdita di prestazioni, ma potrebbe essere molto trascurabile, a seconda delle esigenze di risorse del gioco originale, ecc.
Ecco una citazione da documentazione di Android su questo:
Before downloading the NDK, you should understand that the NDK will not benefit most apps. As a developer, you need to balance its benefits against its drawbacks. Notably, using native code on Android generally does not result in a noticable performance improvement, but it always increases your app complexity. In general, you should only use the NDK if it is essential to your app—never because you simply prefer to program in C/C++.
(Bad) Esempio (che illustra l'ultimo punto): Ho implementato l'algoritmo di pathfinder A * in Java. Ho anche realizzato una piccola e semplice dimostrazione grafica come un'applicazione Android. Ho quindi implementato lo stesso algoritmo in C. Quando eseguivo benchmark separati del codice Java e C, C era talvolta 2-3 volte più veloce (specialmente se ci fosse un sacco di GC quando si eseguiva il codice Java). Così ho modificato la mia app Android per Java per far sì che usasse il codice C tramite JNI. Mentre il progetto è diventato molto più complicato (anche quando si utilizza l'eccellente Sequoyah plug-in Eclipse) le prestazioni effettive il guadagno ora era più simile al 10-20%, non era vicino al 200-300% che stavo vedendo quando eseguivo separatamente la versione Java e C di questo particolare codice.
Come mai (e qui cito dalla memoria) uno dei primi libri di Android (dell'era di versione 2 di Android) ha fornito un esempio avanzato di prendere il codice sorgente di Quake C ++ e usare JNI per trasformarlo in un'app Android in 20 pagine (circa 2-3 ore di lavoro). Se invece il codice Quake C ++ fosse stato tradotto in Java (centinaia di migliaia di righe di codice), ci sarebbe voluto molto più tempo. E dal momento che anche i dispositivi Android di quel periodo erano in grado di "nascondere" le penalita 'prestazionali con JNI che chiamava il gioco Quake, ha fatto un buon compromesso per usare JNI qui.