JDK-7071246 : Enclosing string literal in parenthesis in switch-case crashes javac
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 7
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS:
    linux_redhat_4.0,solaris_10,windows_xp,windows_vista,windows_7 linux_redhat_4.0,solaris_10,windows_xp,windows_vista,windows_7
  • CPU: x86,sparc
  • Submitted: 2011-07-26
  • Updated: 2015-08-19
  • Resolved: 2012-02-24
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availabitlity Release.

To download the current JDK release, click here.
JDK 7 JDK 8
7u2Resolved 8 b01Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.7.0"
Java(TM) SE Runtime Environment (build 1.7.0-b147)
Java HotSpot(TM) Client VM (build 21.0-b17, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

EXTRA RELEVANT SYSTEM CONFIGURATION :
PROCESSOR_ARCHITECTURE=AMD64
PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 23 Stepping 6, GenuineInte
PROCESSOR_LEVEL=6
PROCESSOR_REVISION=1706
  ProgramData=C:\ProgramData
  ProgramFiles=C:\Program Files
  ProgramFiles(x86)=C:\Program Files (x86)
  ProgramW6432=C:\Program Files
SESSIONNAME=Console
SystemDrive=C:
SystemRoot=C:\Windows

A DESCRIPTION OF THE PROBLEM :
Running javac on a program which contains a string literal enclosed in parenthesis like in the example listed below causes javac to throw  NullPointerException and terminate.

...
switch (s) {
 case ("xyz"): // enclosing the string literal in parenthesis causes javac to crash
    ...
}
...

Note:
- Removing the parenthesis from this program helps resolve the issue.
- Replacing the String with int in the example will not reproduce this issue and hence using parenthesis with int literal in 'case' is handled well.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create a file named Test.java with the following content:

=== Begin file Test.java ===
public class Test {
    public static void main(String args[]) {
        switch(args[0]) {
            case("hello"):
                System.out.println("hello!!");
                break;
            default:
                System.out.println("hi!");
        }
    }
}
=== End of file Test.java ===

Save the file and execute the following from the command prompt:

javac Test.java

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Test.class is expected to be created as a result of successful compilation.
ACTUAL -
javac crashes with the following error message:

C:\Temp>"C:\Program Files (x86)\Java\jdk1.7.0\bin\javac.exe" Test.java
An exception has occurred in the compiler (1.7.0). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport)  after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report.  Thank you.
java.lang.NullPointerException
        at com.sun.tools.javac.comp.Lower.visitStringSwitch(Lower.java:3456)
        at com.sun.tools.javac.comp.Lower.visitSwitch(Lower.java:3357)
        at com.sun.tools.javac.tree.JCTree$JCSwitch.accept(JCTree.java:959)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2160)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:70)
        at com.sun.tools.javac.tree.TreeTranslator.visitBlock(TreeTranslator.java:160)
        at com.sun.tools.javac.comp.Lower.visitBlock(Lower.java:3311)
        at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:781)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2160)
        at com.sun.tools.javac.tree.TreeTranslator.visitMethodDef(TreeTranslator.java:144)
        at com.sun.tools.javac.comp.Lower.visitMethodDefInternal(Lower.java:2619)
        at com.sun.tools.javac.comp.Lower.visitMethodDef(Lower.java:2538)
        at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:669)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2160)
        at com.sun.tools.javac.comp.Lower.visitClassDef(Lower.java:2283)
        at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:591)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2160)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2180)
        at com.sun.tools.javac.comp.Lower.translateTopLevelClass(Lower.java:3650)
        at com.sun.tools.javac.main.JavaCompiler.desugar(JavaCompiler.java:1393)
        at com.sun.tools.javac.main.JavaCompiler.desugar(JavaCompiler.java:1271)
        at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:870)
        at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:829)
        at com.sun.tools.javac.main.Main.compile(Main.java:417)
        at com.sun.tools.javac.main.Main.compile(Main.java:331)
        at com.sun.tools.javac.main.Main.compile(Main.java:322)
        at com.sun.tools.javac.Main.compile(Main.java:76)
        at com.sun.tools.javac.Main.main(Main.java:61)

C:\Temp>

ERROR MESSAGES/STACK TRACES THAT OCCUR :
C:\Temp>"C:\Program Files (x86)\Java\jdk1.7.0\bin\javac.exe" Test.java
An exception has occurred in the compiler (1.7.0). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport)  after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report.  Thank you.
java.lang.NullPointerException
        at com.sun.tools.javac.comp.Lower.visitStringSwitch(Lower.java:3456)
        at com.sun.tools.javac.comp.Lower.visitSwitch(Lower.java:3357)
        at com.sun.tools.javac.tree.JCTree$JCSwitch.accept(JCTree.java:959)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2160)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:70)
        at com.sun.tools.javac.tree.TreeTranslator.visitBlock(TreeTranslator.java:160)
        at com.sun.tools.javac.comp.Lower.visitBlock(Lower.java:3311)
        at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:781)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2160)
        at com.sun.tools.javac.tree.TreeTranslator.visitMethodDef(TreeTranslator.java:144)
        at com.sun.tools.javac.comp.Lower.visitMethodDefInternal(Lower.java:2619)
        at com.sun.tools.javac.comp.Lower.visitMethodDef(Lower.java:2538)
        at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:669)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2160)
        at com.sun.tools.javac.comp.Lower.visitClassDef(Lower.java:2283)
        at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:591)
        at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2160)
        at com.sun.tools.javac.comp.Lower.translate(Lower.java:2180)
        at com.sun.tools.javac.comp.Lower.translateTopLevelClass(Lower.java:3650)
        at com.sun.tools.javac.main.JavaCompiler.desugar(JavaCompiler.java:1393)
        at com.sun.tools.javac.main.JavaCompiler.desugar(JavaCompiler.java:1271)
        at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:870)
        at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:829)
        at com.sun.tools.javac.main.Main.compile(Main.java:417)
        at com.sun.tools.javac.main.Main.compile(Main.java:331)
        at com.sun.tools.javac.main.Main.compile(Main.java:322)
        at com.sun.tools.javac.Main.compile(Main.java:76)
        at com.sun.tools.javac.Main.main(Main.java:61)

C:\Temp>

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
//
// File name: Test.java
//
public class Test {
    public static void main(String args[]) {
        switch(args[0]) {
            case("hello"):
                System.out.println("hello!!");
                break;
            default:
                System.out.println("hi!");
        }
    }
}
=== End of file Test.java ===
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Remove the parenthesis from around the sting literal:


=== Begin file Test.java ===
public class Test {
    public static void main(String args[]) {
        switch(args[0]) {
            case "hello":  // workaround is to remove the parenthesis
                System.out.println("hello!!");
                break;
            default:
                System.out.println("hi!");
        }
    }
}
=== End of file Test.java ===

Comments
SUGGESTED FIX # HG changeset patch # User darcy # Date 1312481737 25200 # Node ID 64b9b7ae33667807e34e17a8e017e9d4adb43c33 # Parent 0d6d41563040e1fa91180cf0a54165bdb2b78827 7071246: Enclosing string literal in parenthesis in switch-case crashes javac Reviewed-by: mcimadamore --- a/src/share/classes/com/sun/tools/javac/comp/Lower.java Wed Jul 27 11:53:17 2011 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java Thu Aug 04 11:15:37 2011 -0700 @@ -3450,6 +3450,7 @@ public class Lower extends TreeTranslato JCExpression expression = oneCase.getExpression(); if (expression != null) { // expression for a "default" case is null + expression = TreeInfo.skipParens(expression); String labelExpr = (String) expression.type.constValue(); Integer mapping = caseLabelToPosition.put(labelExpr, casePosition); Assert.checkNull(mapping); @@ -3555,8 +3556,8 @@ public class Lower extends TreeTranslato if (isDefault) caseExpr = null; else { - caseExpr = make.Literal(caseLabelToPosition.get((String)oneCase. - getExpression(). + caseExpr = make.Literal(caseLabelToPosition.get((String)TreeInfo.skipParens(oneCase. + getExpression()). type.constValue())); } --- a/test/tools/javac/StringsInSwitch/StringSwitches.java Wed Jul 27 11:53:17 2011 -0700 +++ b/test/tools/javac/StringsInSwitch/StringSwitches.java Thu Aug 04 11:15:37 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 6827009 + * @bug 6827009 7071246 * @summary Positive tests for strings in switch. * @author Joseph D. Darcy */ @@ -36,6 +36,7 @@ public class StringSwitches { failures += testPileup(); failures += testSwitchingTwoWays(); failures += testNamedBreak(); + failures += testExtraParens(); if (failures > 0) { throw new RuntimeException(); @@ -260,4 +261,19 @@ public class StringSwitches { result |= (1<<5); return result; } + + private static int testExtraParens() { + int failures = 1; + String s = "first"; + + switch(s) { + case (("first")): + failures = 0; + break; + case ("second"): + throw new RuntimeException("Should not be reached."); + } + + return failures; + } }
2011-08-04

PUBLIC COMMENTS See http://hg.openjdk.java.net/jdk8/tl/langtools/rev/64b9b7ae3366
2011-08-04

EVALUATION Parens should be skipped during code generation.
2011-07-27