Nota : sebbene io stia utilizzando ARM SAM3X8E in questo esempio, lo sto solo utilizzando come esempio concreto e la risposta a questa domanda potrebbe essere facilmente fornita utilizzando qualsiasi altro MCU come AVR, ecc.
Ho una domanda pazza . In realtà, è più che altro che confermare la mia conoscenza dell'architettura di computer di basso livello più di ogni altra cosa, e non è necessariamente qualcosa che cercherò di fare davvero.
Sono interessato a comprendere il processo e gli strumenti coinvolti nella scrittura di un'app Java su, ad esempio, una macchina Linux o Windows, e quindi la compilazione incrociata di quell'app in un'immagine che può essere direttamente trasmessa a un MCU, come ad esempio il ARM SAM3X8E. Lo so, pazzo.
Perché mai vorrei farlo, sarebbe la prima risposta di una persona sana di mente. Anche in questo caso:
- Questa domanda è più che altro sulla conferma / chiarimento della mia comprensione della programmazione / architettura di computer di basso livello; ma
- Una ragione possibile per farlo sarebbe in uno scenario in cui io ho per avere un chip MCU / ARM in esecuzione un'applicazione (non una macchina Linux o altro), ma il l'applicazione è così complicata che scriverlo in C e quindi mantenerlo sarebbe un'impresa monumentale. Ma, in Java, con la sua potente sintassi, la struttura dei dati e l'enorme ecosistema di librerie / componenti OSS di terze parti che possono essere sfruttati, scrivere l'app è molto più semplice.
Anche se non sei ancora convinto del mio caso d'uso sopra (che, sarei interessato al perché), sono ancora interessato a vedere come una tale soluzione potrebbe essere brutale forzata lavorare.
Se dovessi combinare una soluzione senza alcun aiuto / guida, ecco cosa farei:
- Implementa la mia JVM in C (lol)
- In definitiva un'app Java viene inserita in una JVM come dati di input (bytecode); e quindi il codice sorgente di questa JVM personalizzata dovrebbe essere hardcoded per cercare uno specifico file di input e leggere bytecode, chiameremo questo file di input
bytecode_input.c
. - Avrei bisogno di una sorta di cross-compiler che abbia preso il bytecode Java (prodotto da
javac
) e lo abbia convertito inbytecode_input.c
. In questo modo, durante la compilazione della mia JVM personalizzata, il bytecode della mia app viene integrato nell'eseguibile eseguibile JVM. - Scrivere la mia JVM personalizzata richiederebbe anche l'implementazione di alcune chiamate di sistema nel codice C, in modo che quando un'applicazione utilizza
FileWriter
per scrivere in un file, la JVM sa quali chiamate di sistema eseguire - Ora vorrei solo assicurarmi che qualunque cosa sia l'output della compilation della JVM è qualcosa che può essere mostrato all'MCU
A meno che mi manchi qualcosa (ancora una volta, comprendendo che i passaggi precedenti non sono affatto banali e che ognuno di essi è probabilmente in preparazione da diversi anni), credo che sia tutto ciò di cui si avrebbe bisogno. Fondamentalmente, scrivo la mia app in Java, la compilo in bytecode, la eseguo attraverso bytecode_file_generator
, trasformandola in un file C denominato bytecode_input.c
. Quel file C viene quindi compilato con il resto della mia JVM (che contiene tutto ciò che una JVM standard ha, GC, gestione della memoria, verificatore di codice, classloader, ecc.), Che produce alcuni file eseguibili / immagine che possono essere mostrati all'MCU.
Se bytecode_input.c
sembra misterioso e vago, ecco qualche pseudo-codice C per quello che intendo:
// This C file simply defines a variable called 'bytecode'
// which contains a static/hardcoded table of all the app's bytecode:
int[] BYTECODE = new int[SIZE_OF_CLASS_FILE] {
103, 1929, 1939, 549, 9939,
3949, 3949, 20304, 28, 238
};
La JVM legge quindi BYTECODE
come input hardcoded anziché a runtime come una normale JVM.
Tipicamente le JVM funzionano su un sistema operativo. Non devo preoccuparmi dei sistemi operativi perché gli MCU eseguono programmi bare metal e, se ho bisogno di funzionalità simili a RTOS, potrei semplicemente inserirli nella JVM personalizzata.
I potrebbe (suppongo) semplicemente creare un cross-compiler molto intelligente che ha convertito l'origine Java della mia app in C, e saltare del tutto coinvolgendo una JVM personalizzata. Ma poi mi perderebbero tutte le cose positive fornite dalla JVM: GC, gestione della memoria, ecc.
Quindi la mia domanda: supponendo che tu possa spingere il magico pulsante " Ok, accetterò questo come un caso valido per ora ... ", il mio approccio qui è fondamentalmente sbagliato? Sto trascurando i principali passaggi / processi?