尽管日志记录级别设置为INFO,并且在运行时该条件永远不会得到满足,但如果“Hi
”不会被初始化,我如何能够以编程方式进行验证?如何以编程方式验证字符串是否已初始化?
if(log.isDebug()){
log.debug("Hi");
}
我的意思是,因为日志记录级别为INFO,该记录将不会有机会来打印消息“嗨”,我关心的是,我怎么能当JRE或JDK会发现/即使条件不满足也不会采取措施来准备“Hi”。
尽管日志记录级别设置为INFO,并且在运行时该条件永远不会得到满足,但如果“Hi
”不会被初始化,我如何能够以编程方式进行验证?如何以编程方式验证字符串是否已初始化?
if(log.isDebug()){
log.debug("Hi");
}
我的意思是,因为日志记录级别为INFO,该记录将不会有机会来打印消息“嗨”,我关心的是,我怎么能当JRE或JDK会发现/即使条件不满足也不会采取措施来准备“Hi”。
转储的字节码。 String常量将会有一个“ldc”操作码。操作码第一次被执行时,实际的字符串将被创建。然后,字符串将被缓存在常量池中,以供后续调用/迭代重用。如果“ldc”从不执行,则不会创建字符串。
嗨热舔,我读了你的其他意见,你可以请扩大你提到的部分“实际上,字符串值通常不会被创建,除非被引用。在字节码中会有一个“load constant”操作码,并且第一次执行该常量将从常量池中提取并创建一个String对象。 “ – 2012-01-27 03:01:27
每个类都有一个常量池,其中一部分是从.class文件中取得的一个不变的结构,但是一部分是一个可以动态更新的表。当引用一个常量字符串时,该表被检查(即is指针null?)来查看该常量是否已经创建,如果不是,则将不变结构中的UTF8值扩展为UTF16,并用于创建(和实体)String,然后将该String的指针存储在表中。 (至少这是它在规范JVM中的工作方式,如果没有对该类进行任何特殊处理。) – 2012-01-27 12:35:36
这段代码没有什么需要“初始化”的;字符串文字“Hi”将被编译器放置到您的.class
文件中,因此无论是否实际使用,它都可以在运行时使用。
实际上,除非被引用,否则通常不会创建字符串值。在字节码中会有一个“load constant”操作码,并且第一次执行该常量将从常量池中提取并创建一个String对象。 – 2012-01-27 02:51:25
所以字符串将会出现在字节码中,但是如果它的值在运行时从不使用,则不会加载到内存中。我想你可以称之为“未初始化”。 – Wyzard 2012-01-27 02:57:52
字符串“嗨”是类定义的一部分。除非编译器可以确定if
的主体是死代码并且不需要文字,那么当类加载器加载该类时,它将加载文字值。由于它是一个编译时常量,它也会自动实现。
编译器无法知道将类加载到某个未知执行环境时,log.isDebug()
的行为。众所周知,记录器类的定义可能会更改,以便isDebug()
返回true
,而不管为记录级别设置的值如何。
我认为字符串字面的“喜”是堆内存初始化只读
你可以做这样的方法和计算内存三角洲:
if(log.isDebug()){
log.debug("literal");
log.debug(memoryUsed());
log.debug("Hi");
log.debug(memoryUsed());
log.debug("initialising");
log.debug(memoryUsed());
string x = "Hi"
log.debug(x);
log.debug(memoryUsed());
}
static long memoryUsed()
{
return runtime.totalMemory() - runtime.freeMemory();
}
所有字符串都是“只读”的,因为它们是不可变的。 “Hi”没有什么特别之处,一旦创建,除了常量池中的字符串总是被实现的,而实习则需要用户为用户创建的字符串执行操作。 – 2012-01-27 02:58:08
字符串文字“嗨” – 2012-01-27 02:33:59
你的意思是's == null'吗? – 2012-01-27 02:34:22
不清楚,请编辑 – 2012-01-27 02:36:39