尝试打印字符串池信息时“此时无法统计”?
我正在学习有关 Java 性能管理的 udemy 课程,但遇到了一个问题,该问题阻止我打印出字符串池的信息。这是我尝试向池中添加一千万个 String对象时得到的结果:
E:IntelliJ ProjectsExploringStringssrc>java -XX:+PrintStringTableStatistics Main
Elapsed time was 28311 ms.
SymbolTable statistics:
Number of buckets : 20011 = 160088 bytes, each 8
Number of entries : 20527 = 492648 bytes, each 24
Number of literals : 20527 = 776904 bytes, avg 37.848
Total footprint : = 1429640 bytes
Average bucket size : 1.026
Variance of bucket size : 1.033
Std. dev. of bucket size: 1.017
Maximum bucket size : 9
statistics unavailable at this moment
这是我使用空的main 方法运行程序时得到的结果:
E:IntelliJ ProjectsExploringStringssrc>java -XX:+PrintStringTableStatistics Main
SymbolTable statistics:
Number of buckets : 20011 = 160088 bytes, each 8
Number of entries : 16615 = 398760 bytes, each 24
Number of literals : 16615 = 608976 bytes, avg 36.652
Total footprint : = 1167824 bytes
Average bucket size : 0.830
Variance of bucket size : 0.837
Std. dev. of bucket size: 0.915
Maximum bucket size : 9
StringTable statistics:
Number of buckets : 65536 = 524288 bytes, each 8
Number of entries : 1734 = 27744 bytes, each 16
Number of literals : 1734 = 112456 bytes, avg 64.854
Total footprsize_t : = 664488 bytes
Average bucket size : 0.026
Variance of bucket size : 0.027
Std. dev. of bucket size: 0.163
Maximum bucket size : 2
这是尝试向池中添加 1000 万个字符串的代码:
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class Main {
public static void main(String[] args) {
Date start = new Date();
List<String> strings = new ArrayList<String>();
for(Integer i = 1; i < 10000000; i++) {
String s = i.toString().intern(); //Adds new string object to the string pool
strings.add(s);
}
Date end = new Date();
System.out.println("Elapsed time was " + (end.getTime() - start.getTime()) + " ms.");
}
}
所以,我的问题是:当我尝试添加 1000 万个对象时,为什么我不能打印出 String 池的信息,但我的导师可以?我无法理解其中的原因,因为这超出了我的 Java 编程水平。谢谢你们。
回答
tl;博士
退出前等待几秒钟,以避免“此时无法统计”问题。
Thread.sleep( Duration.ofSeconds( 5 ).toMillis() )
细节
如果您指的是控制台上的该消息:
暂时无法统计
……我用和你类似的代码也经历过同样的事情。
package work.basil.example;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
public class Stringer
{
public static void main ( String[] args )
{
Instant start = Instant.now();
System.out.println( "Starting run at:" + start + ". Runtime.version(): " + Runtime.version() );
List < String > strings = new ArrayList < String >();
for ( int i = 1 ; i < 10_000_000 ; i++ )
{
String s = String.valueOf( i ).intern(); // Adds new string object to the string pool.
strings.add( s );
}
System.out.println( "Elapsed time was " + Duration.between( start , Instant.now() ) );
}
}
在 IntelliJ 2020.3.1 中使用来自 AdaptOpenJDK 的 Java 15 在 Intel 上的 macOS Mojave 上运行时。
/Library/Java/JavaVirtualMachines/adoptopenjdk-15.jdk/Contents/Home/bin/java -XX:+PrintStringTableStatistics --enable-preview -javaagent:/Users/basilbourque/Library/Application Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/203.6682.168/IntelliJ IDEA 2020.3 EAP.app/Contents/lib/idea_rt.jar=52178:/Users/basilbourque/Library/Application Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/203.6682.168/IntelliJ IDEA 2020.3 EAP.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/basilbourque/IdeaProjects/ExampleJava/target/classes:/Users/basilbourque/.m2/repository/com/h2database/h2/1.4.200/h2-1.4.200.jar:/Users/basilbourque/.m2/repository/com/thedeanda/lorem/2.1/lorem-2.1.jar:/Users/basilbourque/.m2/repository/org/postgresql/postgresql/42.2.18/postgresql-42.2.18.jar:/Users/basilbourque/.m2/repository/org/checkerframework/checker-qual/3.5.0/checker-qual-3.5.0.jar:/Users/basilbourque/.m2/repository/org/apache/commons/commons-csv/1.8/commons-csv-1.8.jar work.basil.example.Stringer
Starting run at:2021-01-04T02:03:34.484633Z. Runtime.version(): 15.0.1+9
Elapsed time was PT6.219106S
SymbolTable statistics:
Number of buckets : 32768 = 262144 bytes, each 8
Number of entries : 2633 = 42128 bytes, each 16
Number of literals : 2633 = 98200 bytes, avg 37.000
Total footprint : = 402472 bytes
Average bucket size : 0.080
Variance of bucket size : 0.079
Std. dev. of bucket size: 0.280
Maximum bucket size : 2
statistics unavailable at this moment
Process finished with exit code 0
......我得到了目前无法获得的相同统计信息。
因此,根据疯狂的猜测,我Thread.sleep在退出前添加了一个等待 5 秒的调用。
try { Thread.sleep( Duration.ofSeconds( 5 ).toMillis() ); } catch ( InterruptedException e ) { e.printStackTrace(); }
所以,在运行这个:
package work.basil.example;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
public class Stringer
{
public static void main ( String[] args )
{
Instant start = Instant.now();
System.out.println( "Starting run at:" + start + ". Runtime.version(): " + Runtime.version() );
List < String > strings = new ArrayList < String >();
for ( int i = 1 ; i < 10_000_000 ; i++ )
{
String s = String.valueOf( i ).intern(); // Adds new string object to the string pool.
strings.add( s );
}
System.out.println( "Elapsed time was " + Duration.between( start , Instant.now() ) );
try { Thread.sleep( Duration.ofSeconds( 5 ).toMillis() ); } catch ( InterruptedException e ) { e.printStackTrace(); }
}
}
我明白了:
/Library/Java/JavaVirtualMachines/adoptopenjdk-15.jdk/Contents/Home/bin/java -XX:+PrintStringTableStatistics --enable-preview -javaagent:/Users/basilbourque/Library/Application Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/203.6682.168/IntelliJ IDEA 2020.3 EAP.app/Contents/lib/idea_rt.jar=52114:/Users/basilbourque/Library/Application Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/203.6682.168/IntelliJ IDEA 2020.3 EAP.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/basilbourque/IdeaProjects/ExampleJava/target/classes:/Users/basilbourque/.m2/repository/com/h2database/h2/1.4.200/h2-1.4.200.jar:/Users/basilbourque/.m2/repository/com/thedeanda/lorem/2.1/lorem-2.1.jar:/Users/basilbourque/.m2/repository/org/postgresql/postgresql/42.2.18/postgresql-42.2.18.jar:/Users/basilbourque/.m2/repository/org/checkerframework/checker-qual/3.5.0/checker-qual-3.5.0.jar:/Users/basilbourque/.m2/repository/org/apache/commons/commons-csv/1.8/commons-csv-1.8.jar work.basil.example.Stringer
Starting run at:2021-01-04T02:02:21.792377Z. Runtime.version(): 15.0.1+9
Elapsed time was PT5.887848S
SymbolTable statistics:
Number of buckets : 32768 = 262144 bytes, each 8
Number of entries : 2635 = 42160 bytes, each 16
Number of literals : 2635 = 98280 bytes, avg 37.000
Total footprint : = 402584 bytes
Average bucket size : 0.080
Variance of bucket size : 0.079
Std. dev. of bucket size: 0.281
Maximum bucket size : 2
StringTable statistics:
Number of buckets : 8388608 = 67108864 bytes, each 8
Number of entries : 10000880 = 160014080 bytes, each 16
Number of literals : 10000880 = 480062480 bytes, avg 48.000
Total footprint : = 707185424 bytes
Average bucket size : 1.192
Variance of bucket size : 1.383
Std. dev. of bucket size: 1.176
Maximum bucket size : 9
Process finished with exit code 0
等待退出后,statistics unavailable at this moment消息消失了,我们得到了完整的统计信息。
我们确实看到Number of literals从几千人跃升至超过一千万人。大概这是由于我们将一千万个数字变成了字符串的循环。
文档?
我试图对此进行研究,以了解PrintStringTableStatistics开关的记录行为。但我找不到任何文件。我不知道现在在哪里可以找到控制台工具java、 等的文档javac。
谁有链接,请发一下。