In looking through the JSTL source, I noticed 40 occurances (listed below) where the code was creating new Boolean objects. In a system where performance is critical, this creation of garbage Boolean objects can increase the overall memory load of a system. It is much preferable to use the Boolean.TRUE and Boolean.FALSE static values in situations where the use of a Boolean is required. It is fairly easy to write a simple public static final helper method (getBoolean(boolean flag)) that does a {if (flag) return Boolean.TRUE; return Boolean.FALSE;} Thanks for you help in improving JSTL's performance. Heath Chiavettone \jakarta- taglibs\standard\src\javax\servlet\jsp\jstl\core\ConditionalTagSupport.java (185,43): pageContext.setAttribute(var, new Boolean(result), scope); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\extra\spath\SPathParser.java (460,27): boolean[] la1tokens = new boolean[20]; \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\adapter\Convert.jav a(129,25): converted = new Boolean(false); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\adapter\Convert.jav a(155,25): converted = new Boolean(false); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\adapter\Convert.jav a(157,25): converted = new Boolean(true); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\adapter\Convert.jav a(159,25): converted = new Boolean(false); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\adapter\Convert.jav a(167,25): converted = new Boolean(false); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\adapter\Convert.jav a(169,25): converted = new Boolean(true); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\adapter\Convert.jav a(171,25): converted = new Boolean(false); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\adapter\Convert.jav a(185,25): converted = new Boolean(false); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\adapter\Convert.jav a(192,25): converted = new Boolean(true); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\AndOpera tor.java(201,22): result = new Boolean(leftSide && rightSide); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\BooleanL iteral.java(185,16): return new Boolean(val); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\Contains Function.java(218,22): result = new Boolean(arg1.indexOf(arg2) != - 1); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\EqualsOp erator.java(237,16): return new Boolean(result); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\GreaterT hanEqualOperator.java(238,16): return new Boolean(result); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\GreaterT hanOperator.java(238,16): return new Boolean(result); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\LessThan EqualOperator.java(238,16): return new Boolean(result); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\LessThan Operator.java(238,16): return new Boolean(result); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\NotEqual sOperator.java(237,16): return new Boolean(result); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\NotFunct ion.java(198,16): return new Boolean(result.booleanValue() == false); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\OrOperat or.java(201,22): result = new Boolean(leftSide || rightSide); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\Parser.j ava(885,54): BooleanFunction jjtn001 = new BooleanFunction(JJTBOOLEANFUNCTION); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\Parser.j ava(1808,29): BooleanLiteral jjtn001 = new BooleanLiteral(JJTBOOLEANLITERAL); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\Parser.j ava(2679,27): boolean[] la1tokens = new boolean[65]; \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\StartsWi thFunction.java(218,22): result = new Boolean(arg1.startsWith (arg2)); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jstl\BooleanLiteral.java (73,45): public static final BooleanLiteral TRUE = new BooleanLiteral ("true"); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jstl\BooleanLiteral.java (74,46): public static final BooleanLiteral FALSE = new BooleanLiteral ("false"); \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jstl\parser\ELParser.java (1093,27): boolean[] la1tokens = new boolean[54]; \jakarta- taglibs\standard\src\org\apache\taglibs\standard\lang\jstl\parser\jsp20 \ELParser.java(1090,27): boolean[] la1tokens = new boolean[54]; \jakarta- taglibs\standard\src\org\apache\taglibs\standard\tag\common\core\ForEachSupport .java(296,29): Boolean[] wrapped = new Boolean[a.length]; \jakarta- taglibs\standard\src\org\apache\taglibs\standard\tag\common\core\ForEachSupport .java(298,26): wrapped[i] = new Boolean(a[i]); \jakarta-taglibs\standard\src\org\apache\taglibs\standard\tlv\JstlCoreTLV.java (206,26): chooseHasWhen.push(new Boolean(true)); \jakarta-taglibs\standard\src\org\apache\taglibs\standard\tlv\JstlCoreTLV.java (222,31): chooseHasOtherwise.push(new Boolean(true)); \jakarta-taglibs\standard\src\org\apache\taglibs\standard\tlv\JstlCoreTLV.java (251,22): chooseHasWhen.push(new Boolean(false)); \jakarta-taglibs\standard\src\org\apache\taglibs\standard\tlv\JstlCoreTLV.java (252,27): chooseHasOtherwise.push(new Boolean(false)); \jakarta-taglibs\standard\src\org\apache\taglibs\standard\tlv\JstlXmlTLV.java (201,40): chooseHasWhen.push(new Boolean(true)); \jakarta-taglibs\standard\src\org\apache\taglibs\standard\tlv\JstlXmlTLV.java (217,31): chooseHasOtherwise.push(new Boolean(true)); \jakarta-taglibs\standard\src\org\apache\taglibs\standard\tlv\JstlXmlTLV.java (239,36): chooseHasWhen.push(new Boolean(false)); \jakarta-taglibs\standard\src\org\apache\taglibs\standard\tlv\JstlXmlTLV.java (240,27): chooseHasOtherwise.push(new Boolean(false));
Do you have some evidence that this leads, in practice, to a performance- problem on any real-world system. The change you're suggesting is minor, so I can just make it as soon as I get a chance, but I'm not inclined to go out of my way to intuit things about system performance without hard evidence. My impression is that any legitimate JIT knows how to optimize this kind of code; object creation is emphatically *not* expensive on nearly all real-world JITs, and code is often made complex out of a mistaken desire to avoid it!
I agree with Shawn the JITs should take care of these kinds of optimization. In fact, if they do, then your approach would penalize the performance, as it would require an extra method call. On the other hand, such static function already exists in JDK 1.4.2: http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Boolean.html#valueOf(boolean) The fact that this function exists suggests that creating new Booleans in fact a decreases performance. If JSTL depended on JDK 1.4.2, we could easily fix this by using replacing the occurrences of "new Boolean(x)" to "Boolean.valueOf(x)", but unfortunately that's not the case. Another option would be Boolean.valueOf(""+x), as JDK 1.3.x has a valueOf(String) method. Just my 2 cents, Felipe
Did a general audit and substituted static values where Boolean objects were created where appropriate. Changes were made to standard HEAD and available in the nightly build and will be available in the upcoming Standard 1.1.1 release. I agree with Shawn and Felipe's assessment that the JIT should take care of this type of optimization so therefore the static helper method won't be implemented. I believe that the added method call may penalize performance.