JDK-8037385 : constant pool errors with -target 1.7 and static default methods
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_7
  • CPU: x86_64
  • Submitted: 2014-03-11
  • Updated: 2014-07-29
  • Resolved: 2014-06-10
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 Availability Release.

To download the current JDK release, click here.
JDK 8 JDK 9
8u20Fixed 9 b19Fixed
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

EXTRA RELEVANT SYSTEM CONFIGURATION :
We are using JDK 8 including the new classes. The IDE doesn't support Java 8 syntax, so we are currently compiling with -source 1.7 and -target 1.7

A DESCRIPTION OF THE PROBLEM :
Compiling with -source 1.7 and -target 1.7 seems to works fine, but execution breaks with a VerifyError if static default methods are used (Funtion.identity(), Comparator.reverseOrder(), etc.).
It states an "Illegal type at constant pool entry 7 in class Dummy". The entry changes depending on the class.

When compiling with -target 1.8 or when using the Eclipse compiler (for java 7) with the java 8 classes, everything works fine.

Solooks like a compiler issue.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the class with
> javac -source 1.7 -target 1.7 Dummy.java
Execute
> java Dummy

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
3
2
1

ACTUAL -
Exception in thread "main" java.lang.VerifyError: Illegal type at constant pool entry 7 in class Dummy
Exception Details:
  Location:
    Dummy.main([Ljava/lang/String;)V @24: invokestatic
  Reason:
    Constant pool index 7 is invalid
  Bytecode:
    0000000: 06bd 0002 5903 1203 5359 0412 0453 5905
    0000010: 1205 53b8 0006 4c2b b800 07b8 0008 2bbb
    0000020: 0009 59b7 000a b900 0b02 00b1

        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Class.java:2688)
        at java.lang.Class.getMethod0(Class.java:2937)
        at java.lang.Class.getMethod(Class.java:1771)
        at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
        at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.function.Consumer;


public class Dummy {
	
	public static void main(String[] args) {
		List<String> strings = Arrays.asList("1", "3", "2");
		Collections.sort(strings, Comparator.<String>reverseOrder());

		strings.forEach(new Consumer<String>() {
			@Override
			public void accept(String t) {
				System.out.println(t);
			}
		});
		
	}
	
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
use Eclipse compiler
use -target 1.8
Bypass any static default methods, like Function.identity().


Comments
Agree with Harold. We need an error check for invocations of static interface methods where source < 8. This is not a problem for (non-static) default methods, because they can be invoked just like abstract interface methods.
05-05-2014

The illegal constant pool entry is an InterfaceMethodRef for an invokestatic bytecode. For JDK 7, invokestatic can only take a MethodRef. See http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.invokestatic "The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (��2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The run-time constant pool item at that index must be a symbolic reference to a method..." Javac should not generate invokestatic instructions with InterfaceMethodRefs for version 7.
02-05-2014

I've done the following: import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.function.Consumer; class Test { public static void main(String[] args) { List<String> strings = Arrays.asList("1", "3", "2"); Collections.sort(strings, Comparator.<String>reverseOrder()); strings.forEach(new Consumer<String>() { @Override public void accept(String t) { System.out.println(t); } }); } } with: javac Test.java javap -v -p *.class > outputJavapTarget8 and: javac -source 7 -target 7 Test.java javap -v -p *.class > outputJavapTarget7 Files outputJavapTarget{7, 8} can be found attached. There is no significant difference in the bytecode generated by javac. The only thing that changes is the major version attribute, as expected. So I think that this is a VM bug rather than a javac one.
27-03-2014

Not in my area, assigning to "automatic" so that it can assigned correctly.
26-03-2014