2012-01-27 33 views
0

尽管日志记录级别设置为INFO,并且在运行时该条件永远不会得到满足,但如果“Hi”不会被初始化,我如何能够以编程方式进行验证?如何以编程方式验证字符串是否已初始化?

if(log.isDebug()){ 
    log.debug("Hi"); 
} 

我的意思是,因为日志记录级别为INFO,该记录将不会有机会来打印消息“嗨”,我关心的是,我怎么能当JRE或JDK会发现/即使条件不满足也不会采取措施来准备“Hi”。

+0

字符串文字“嗨” – 2012-01-27 02:33:59

+0

你的意思是's == null'吗? – 2012-01-27 02:34:22

+0

不清楚,请编辑 – 2012-01-27 02:36:39

回答

4

转储的字节码。 String常量将会有一个“ldc”操作码。操作码第一次被执行时,实际的字符串将被创建。然后,字符串将被缓存在常量池中,以供后续调用/迭代重用。如果“ldc”从不执行,则不会创建字符串。

+0

嗨热舔,我读了你的其他意见,你可以请扩大你提到的部分“实际上,字符串值通常不会被创建,除非被引用。在字节码中会有一个“load constant”操作码,并且第一次执行该常量将从常量池中提取并创建一个String对象。 “ – 2012-01-27 03:01:27

+0

每个类都有一个常量池,其中一部分是从.class文件中取得的一个不变的结构,但是一部分是一个可以动态更新的表。当引用一个常量字符串时,该表被检查(即is指针null?)来查看该常量是否已经创建,如果不是,则将不变结构中的UTF8值扩展为UTF16,并用于创建(和实体)String,然后将该String的指针存储在表中。 (至少这是它在规范JVM中的工作方式,如果没有对该类进行任何特殊处理。) – 2012-01-27 12:35:36

0

这段代码没有什么需要“初始化”的;字符串文字“Hi”将被编译器放置到您的.class文件中,因此无论是否实际使用,它都可以在运行时使用。

+1

实际上,除非被引用,否则通常不会创建字符串值。在字节码中会有一个“load constant”操作码,并且第一次执行该常量将从常量池中提取并创建一个String对象。 – 2012-01-27 02:51:25

+0

所以字符串将会出现在字节码中,但是如果它的值在运行时从不使用,则不会加载到内存中。我想你可以称之为“未初始化”。 – Wyzard 2012-01-27 02:57:52

3

字符串“嗨”是类定义的一部分。除非编译器可以确定if的主体是死代码并且不需要文字,那么当类加载器加载该类时,它将加载文字值。由于它是一个编译时常量,它也会自动实现。

编译器无法知道将类加载到某个未知执行环境时,log.isDebug()的行为。众所周知,记录器类的定义可能会更改,以便isDebug()返回true,而不管为记录级别设置的值如何。

0

我认为字符串字面的“喜”是堆内存初始化只读

你可以做这样的方法和计算内存三角洲:

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(); 
     } 
+0

所有字符串都是“只读”的,因为它们是不可变的。 “Hi”没有什么特别之处,一旦创建,除了常量池中的字符串总是被实现的,而实习则需要用户为用户创建的字符串执行操作。 – 2012-01-27 02:58:08