总览
一个常见的问题是一段代码创建多少个对象或多少个字符串。 答案通常不是您的想法,也不是您真正需要知道的。 了解何时创建对象是很有用的,但是有很多其他因素通常要考虑的重要得多,这可能意味着应用程序总数不是您所想的。
字符串不是一个单一的对象
字符串包装char []。 这意味着当您看到新的String时,可能还会涉及到新的char []。 如果您对String做+,则可以使用StringBuilder(来自Java 5.0),它也可以包装char []。 这意味着通常在Java中创建的char []比String对象更多。 有时char []是JVM中最常见的对象类型。
字符串文字仍然是字符串
一个常见的误解是String文字不计算在内。 在至少运行一次代码之后,它们不会添加到总数中,但是大多数情况下,问题是关于一次运行的代码。 即字符串文字仍然计数。
另一个常见的误解是字符串文字被加载时。 在Java 6及更早版本中,它们是在加载Class时加载的,但是现在(Java 7+)在首次使用时已加载。 这意味着首次出现String文字的一段代码将创建新的String对象。
JVM使用字符串,其中很多。
JVM使用Java代码,并且使用字符串。 用于加载您的类的ClassLoader使用字符串。 您要加载的类的名称是一个String,所有系统属性和创建的所有环境变量都是如此,以便您可以运行您的程序,它们都是String,包括值和键名。
让我们考虑一个Hello World程序,并查看创建了多少个String,以便此程序可以运行。 是0、1还是2个字符串,看看是否可以猜测实际创建了多少个字符串。
public class HowManyStrings {public static void main(String[] args) throws IOException {System.out.println("Hello world");System.in.read();}
}
该程序在System.in.read()上停止; 让我把堆放了。 假设没有GC,实用程序jmap可以给出当前堆上对象数量的直方图计数,这将是创建的数量。
如您所见,字符串的数目为2490。如果我还有更多的环境变量或Java的其他更新,则数字将有所不同。
简而言之,如果您在代码中争论2到5个String,则可以看到,当代码运行一次时,您可能会丢失大多数String。
但是,如果我多次调用代码怎么办?
如果您正在谈论数百万次,这很可能很重要,但这就是问题。 JVM将优化多次调用的代码,并且它可以做两件事。
消除死代码
JIT检测到的代码不会做任何有用的事情,可以将其删除。 JIT非常擅长此操作,很可能您正在查看的示例也没有做任何有用的事情。 但是,在现实世界的代码中,希望它可以做一些有用的事情,这是下一个优化有用的地方。
转义分析
JIT可以查看一个方法(或内联调用的所有方法后该方法的外观),并查看对象是否转义了该方法。 如果它不能逃脱该方法,则可以将其放在堆栈上,或者有效地将其字段解包到堆栈上。 这意味着不会在堆上创建任何对象,并且实际上甚至不必创建对象标头,它是所有字段,可能不需要创建任何字段。 简而言之,仅仅因为您在代码中看到了新的String并不意味着JIT必须实际创建一个对象,只要它对结果没有影响(除非您在计算创建的对象的数量)
结论
即使是很小的应用程序创建的字符串数量也可能远远超过您想像的用途,但是调用了足够的次数,您可能会发现方法根本不再创建任何对象。
2015-10-07
翻译自: https://www.javacodegeeks.com/2015/10/common-misconception-how-many-objects-does-this-create.html