在本文中,会带你如何使用最新的Java,让你最多可以节省25%的堆内存,这意味着更少的云服务费用。
您是否知道可以毫不费力地节省多达25%的堆内存和云服务器费用呢?好吧,那是真的。最近,最新的Java版本里中添加了许多令人兴奋的功能,在本文中,我将介绍其中的一项功能,因此请耐心等待。
众所周知,在任何的Java编写的项目中,字符串是应用程序中使用最多的对象。实际上,它几乎占据了Java应用程序堆大小的一半。
在深入探讨这一问题之前,让我回答您一个明显的问题,我知道您会问:Java中的String是如何产生的呢?
好吧,字符串不过是一个字符数组,至少过去是这样。如果从JDK 8打开String类,您将可以看到它。
但是,与C不同,在Java编程语言中,char数组不是String,并且String或char数组都不以'\ u0000'(NUL字符)结尾。尽管如此,Java中的String对象也是不可变的,这意味着String的内容永远不会改变,而char数组具有可变的元素。
在Java 8和Java 8之前的版本中,在String中使用char数组。一个char占用2个字节的内存。这意味着,要存储一个字符,您需要16位内存。例如,如果您编写“ Hello”,则需要一个数组对象,该对象将包含5个字符
字符串的总大小 = 数组对象本身的大小 + 5个字符的大小 + 数组的长度为整数
= 8个字节用于数组对象标头 + 5 * 2个字节 + 4个字节
= 8 + 10 + 4
= 22字节
但是,当今大多数西方本地人只需要8位字节数组即可对其进行编码。这就是Java 11引入新的紧凑型字符串的原因,该紧凑型字符串使用8位字节数组而不是char数组对字符串进行编码。除非他们明确需要16位字符。这些字符串被称为 紧凑字符串(CompactString)。
可参考JEP:http://openjdk.java.net/jeps/254
因此,Java 11中平均字符串的大小大约是Java 8中相同字符串的大小的一半。 平均而言,典型Java堆的50%可能被字符串对象消耗。这将因应用程序的不同而有所不同,但是平均而言,使用Java 11运行的此类程序的堆要求仅为使用Java 8运行的同一程序的75%。
这是巨大的节省。
-XX:+CompactStrings标志控制此功能
如果要禁用它,可以使用此标志 -XX:-CompactStrings。
下面我们说说,CompactString的一些知识点。Compact String是作为JDK 9的一部分在JVM中引入的性能增强之一。直到JDK 8,无论何时我们创建一个String对象,然后在内部将其表示为char [],它由String对象的字符组成。
Compact String有什么需要?
JDK8之前的String版本(或更低版本)
这里值得注意的是:在上述程序中,我们可以看到在Java 9之前,Java仅将String对象表示为char []。假设我们创建一个String对象,并且该对象包含可以使用1个字节表示的字符。代替将对象表示为byte [],它只会创建char [],这将消耗更多的内存。JDK开发人员分析说,大多数字符串只能使用Latin-1字符集表示。Latin-1字符可以存储在一个字节中,恰好是char大小的一半。这将提高String的性能。
JDK 9之后的String版本
注意:现在的问题是,如何区分LATIN-1和UTF-16表示形式?Java开发人员引入了一个最终的字节变量编码器,该编码器保留了有关字符表示的信息。编码器值的值可以是:
因此,就性能而言,新的String实现在Java 9中称为Compact String优于Java 9之前的String,因为与JDK 9堆中的String相比,Compact String使用的区域大约占一半。
我们举个栗子来说明这些区别:
这段代码如果在Java8或更早的版上运行,有以下的一些关键点:
如果在JDK9之后,则有以下的关键点: