9

根据这个问题,在 Java 中确定对象内存大小的标准方法是使用 java.lang.instrumentation。经过一些研究,似乎没有 Scala 特定的方法来实现这一点,所以 Java 方法也应该适用于此。

不幸的是,对于没有 Java 背景的 Scala 程序员来说,在 Scala 中采用这种技术并不完全简单。我的问题是:

问题 1

这里到底发生了什么?我猜我们必须将类ObjectSizeFetcher放在单独的 JAR 中的原因是为了确保它在我们想要使用它的实际程序之前以某种方式加载。Premain-Class我认为没有条目和参数就不可能使用仪器-javaagent:TheJarContainingObjectFetcher.jar

问题2

有没有一种简单的方法可以在 SBT 中实现完整的工作流程?目前我只看到一个有点麻烦的解决方案:我首先必须建立一个辅助 SBT 项目,在其中定义ObjectSizeFetcher并打包到 JAR 中。到目前为止,我还没有弄清楚如何Premain-Class在打包过程中自动将条目添加到 JAR 中,所以我必须手动解决这个问题。我可以将生成的 JAR 添加到我想要使用的项目的本地库中getObjectSize。对于这个项目,我现在必须启用fork in run和使用javaOptions in run += "-javaagent:TheJarContainingObjectFetcher.jar". 是否有更简单(且侵入性更小)的工作流程可以在现有 SBT 项目中快速使用仪器?也许我可以直接告诉 SBTPremain-Class以使这个辅助 JAR 变得不必要?

问题 3

你会推荐一种完全不同的方法来评估 Scala 中对象的内存使用情况吗?

4

2 回答 2

2

答案1:是的,如果你想要iinstrumentation,你需要获取一个实例。如果没有 Premain-Class 和 -javaagent,您可能无法获得它。

答案 2:您可以(并且可能需要)使用类加载器并创建一个非常简单的引导项目(在 Java 中或在带有 Proguard 的 Scala 中)。有两个原因:

第一个原因:方便。您可以使用 java.net.URLClassLoader 来包含标准 Scala 库和项目的 classes 目录。测试时不再需要在 JAR 中重新打包它。

第二个原因:防止 JAR 地狱。您可能知道 Scala 不是二进制兼容的。您还应该知道 Java 代理是在同一个类加载器中与应用程序一起加载的。如果类加载器包含 Scala 库,则应用程序不能简单地使用另一个 Scala 版本。

但是,如果 Java 代理不直接使用 Scala 库(例如,它是一个引导应用程序并在另一个类加载器中加载真正的代理及其库),则被检测的应用程序可以自由使用任何 Scala 库。

答案 3:我可能也会使用仪器。

于 2013-01-04T19:04:33.590 回答
2

答案3:你可以看一下JOL(Java Object Layout)ktoso/sbt-jol的显示,即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
于 2016-06-16T08:36:17.140 回答