2012-11-30 8 views
9

Secondo this question, il metodo standard per determinare la dimensione della memoria di un oggetto in Java è utilizzando java.lang.instrumentation. Dopo alcune ricerche, sembra che non ci sia un modo specifico di Scala per ottenere questo, quindi l'approccio Java dovrebbe valere anche qui.determinare la dimensione dell'oggetto: il modo migliore per utilizzare la strumentazione in scala/sbt

Sfortunatamente, per un programmatore Scala senza sfondo Java non è del tutto semplice adattare questa tecnica in Scala. Le mie domande sono:

Domanda 1

Che cosa esattamente sta succedendo qui? Immagino che il motivo per cui dobbiamo inserire una classe come ObjectSizeFetcher in un JAR separato sia quello di assicurarsi che sia in qualche modo caricato prima del programma attuale in cui vogliamo usarlo. Suppongo che non sia possibile utilizzare la strumentazione senza la voce Premain-Class e il parametro -javaagent:TheJarContainingObjectFetcher.jar?

Domanda 2

C'è un modo semplice per implementare il flusso di lavoro completo in SBT? Attualmente vedo solo una soluzione un po 'ingombrante: prima devo impostare un progetto SBT secondario dove definisco lo ObjectSizeFetcher e lo impacchetta in un JAR. Finora non ho capito come aggiungere automaticamente la voce Premain-Class al JAR durante l'imballaggio, quindi dovrei risolverlo manualmente. Di quanto posso aggiungere il JAR risultante alle librerie locali del progetto in cui voglio usare getObjectSize. Per questo progetto ora devo abilitare fork in run e utilizzare javaOptions in run += "-javaagent:TheJarContainingObjectFetcher.jar". Esiste un flusso di lavoro più semplice (e meno intrusivo) per utilizzare rapidamente la strumentazione all'interno di un progetto SBT esistente? Forse posso dire a SBT direttamente su un Premain-Class per rendere questo JAR secondario non necessario?

Domanda 3

Consiglieresti un modo completamente diverso di valutare l'utilizzo della memoria di un oggetto in Scala?

+1

mi piacerebbe che ci fosse stato un modo più snello per realizzare questo per Scala all'interno della SBT console REPL .... – matanster

risposta

2

Risposta 1: Sì, se si desidera la strumentazione, è necessario ottenere un'istanza. Probabilmente non puoi ottenerlo senza Premain-Class e -javaagent.

Risposta 2: È possibile (e potrebbe essere necessario) utilizzare i classloader e creare un progetto di bootstrap molto semplice (in Java o in Scala con Proguard). Ci sono due ragioni:

La prima ragione: convenienza. È possibile utilizzare java.net.URLClassLoader per includere la libreria Scala standard e la directory classes del progetto. Non sarà più necessario riconfezionarlo in JAR durante il test.

Il secondo motivo: prevenire l'inferno JAR. Probabilmente sai che Scala non è compatibile con i binari. Dovresti anche sapere che l'agente Java è caricato con l'applicazione nello stesso classloader. Se il classloader include la libreria di Scala, l'applicazione non può semplicemente usare un'altra versione di Scala.

Tuttavia, se l'agente Java non utilizza direttamente la libreria Scala (ad esempio è un'applicazione di bootstrap e carica l'agente reale e le relative librerie in un altro programma di caricamento classi), l'applicazione strumentata è libera di utilizzare qualsiasi libreria Scala.

Risposta 3: Probabilmente userò anche la strumentazione.

2

Risposta 3: si può avere uno sguardo a ktoso/sbt-jol che visualizza la JOL (Java Object Layout), vale a dire l'analisi degli schemi di layout oggetto nella JVM

// project/plugins.sbt 
addSbtPlugin("pl.project13.sbt" % "sbt-jol" % pluginVersionHere) 

It does include the size: 

> jol:internals example.Entry 

... 
[info] example.Entry object internals: 
[info] OFFSET SIZE TYPE DESCRIPTION     VALUE 
[info]  0 12  (object header)    N/A 
[info]  12  4 int Entry.value     N/A 
[info]  16  4 String Entry.key      N/A 
[info]  20  4  (loss due to the next object alignment) 
[info] Instance size: 24 bytes 
[info] Space losses: 0 bytes internal + 4 bytes external = 4 bytes total