2012-11-30 6 views
9

Nach this question ist die Standardmethode zum Ermitteln der Speichergröße eines Objekts in Java mithilfe von java.lang.instrumentation. Nach einigen Nachforschungen sieht es so aus, als gäbe es keinen Scala-spezifischen Weg, um dies zu erreichen, daher sollte der Java-Ansatz auch hier gelten.ermitteln Größe des Objekts: beste Möglichkeit, Instrumentierung in scala/sbt zu verwenden

Leider ist es für einen Scala-Programmierer ohne Java-Hintergrund nicht ganz einfach, diese Technik in Scala anzupassen. Meine Fragen sind:

Frage 1

Was genau ist hier passiert? Ich denke, der Grund, warum wir eine Klasse wie ObjectSizeFetcher in eine separate JAR setzen müssen, ist sicherzustellen, dass es irgendwie vor dem eigentlichen Programm geladen wird, wo wir es benutzen wollen. Ich nehme an, es ist nicht möglich, Instrumente ohne den Eintrag Premain-Class und den Parameter zu verwenden?

Frage 2

Gibt es eine einfache Möglichkeit, den kompletten Arbeitsablauf in SBT zu implementieren? Derzeit sehe ich nur eine etwas umständliche Lösung: Zuerst muss ich ein sekundäres SBT-Projekt einrichten, wo ich ObjectSizeFetcher definiere und es in ein JAR verpacken. Bis jetzt habe ich nicht herausgefunden, wie man automatisch den Premain-Class Eintrag zum JAR während des Verpackens hinzufügt, also würde ich das manuell lösen müssen. Dann kann ich die resultierende JAR zu den lokalen Bibliotheken des Projekts hinzufügen, wo ich getObjectSize verwenden möchte. Für dieses Projekt muss ich jetzt fork in run aktivieren und javaOptions in run += "-javaagent:TheJarContainingObjectFetcher.jar" verwenden. Gibt es einen einfacheren (und weniger aufdringlichen) Arbeitsablauf, um die Instrumentierung innerhalb eines bestehenden SBT-Projekts schnell zu verwenden? Vielleicht kann ich SBT direkt über eine Premain-Class sagen, um diese sekundäre JAR unnötig zu machen?

Frage 3

Möchten Sie eine ganz andere Art und Weise empfehlen die Speichernutzung eines Objekts in Scala zu bewerten?

+1

ich es wünschte, ein schlanker Weg gewesen war, dass innerhalb der SBT für Scala zu erreichen Konsole REPL .... – matanster

Antwort

2

Antwort 1: Ja, wenn Sie iinstrumentation möchten, müssen Sie eine Instanz erhalten. Sie können es wahrscheinlich nicht ohne Premain-Class und -Javaagent erhalten.

Antwort 2: Sie können (und müssen) Klassen-Loader verwenden und ein sehr einfaches Bootstrap-Projekt erstellen (in Java oder in Scala mit Proguard). Es gibt zwei Gründe:

Der erste Grund: Bequemlichkeit. Sie können java.net.URLClassLoader verwenden, um die Standard-Scala-Bibliothek und das Klassenverzeichnis Ihres Projekts einzuschließen. Sie müssen es beim Testen nicht mehr in JAR neu packen.

Der zweite Grund: JAR-Hölle zu verhindern. Sie wissen wahrscheinlich, dass Scala nicht binärkompatibel ist. Sie sollten auch wissen, dass der Java-Agent mit der Anwendung im selben Classloader geladen ist. Wenn der Classloader die Scala-Bibliothek enthält, kann die Anwendung nicht einfach eine andere Scala-Version verwenden.

Wenn der Java-Agent jedoch nicht direkt die Scala-Bibliothek verwendet (z. B. eine Bootstrap-Anwendung und den realen Agenten und seine Bibliotheken in einen anderen Classloader lädt), kann die instrumentierte Anwendung jede Scala-Bibliothek verwenden.

Antwort 3: Ich würde wahrscheinlich auch Instrumentation verwenden.

2

Antwort 3: können Sie einen Blick auf ktoso/sbt-jol haben, die die JOL (Java Object Layout) zeigt, dh die Analyse von Objekt Layout Schemata in JVMs

// 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