-
Bug
-
Resolution: Cannot Reproduce
-
P4
-
8
-
x86_64
-
windows_7
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8042422 | 8u20 | Robert Field | P4 | Closed | Cannot Reproduce |
FULL PRODUCT VERSION :
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) Client VM (build 25.0-b70, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Windows 7 64 bits, Windows 8.1 64 bits
A DESCRIPTION OF THE PROBLEM :
Method references cannot be used with method taht returns generic type.
^^^^^^^^^^^^
getObject()::doSomething
The getObject could not be resolved if it returns a generic type
When a parent class defines a generic type with a getter.
This getter cannot be called from a child class with a method reference.
Althought if we create a new getter with the right forced type the method is correctly called.
Provided sample code reproduced the problem
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run TestFailure class
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The handler defined into AbstractClass is correctly resolved and called
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
Exception Details:
Location:
TestFailure.main([Ljava/lang/String;)V @13: invokedynamic
Reason:
Type 'Handler' (current frame, stack[1]) is not assignable to 'CustomHandler'
Current Frame:
bci: @13
flags: { }
locals: { '[Ljava/lang/String;', 'ConcreteClass' }
stack: { 'ConcreteClass', 'Handler' }
Bytecode:
0000000: bb00 1059 b700 124c 2b2b b600 13ba 001a
0000010: 0000 b600 1b2b b600 1fb1
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 ----------
// Define the generic handler
public abstract class AbstractClass <H extends Handler >{
private H parentHandler;
public AbstractClass(H parentHandler) {
super();
this.parentHandler = parentHandler;
}
public H getHandler() {
return parentHandler;
}
}
//Call the generic handler
public class ConcreteClass extends AbstractClass<CustomHandler> {
private Handler localHandler;
public ConcreteClass() {
//Define parentHandler
super(new CustomHandler());
}
public void setLocalHandler(Handler handler){
this.localHandler = handler;
}
public CustomHandler getForcedHandler() {
//return the parent handler
return getHandler();
}
public void check() {
localHandler.handle(new Object());
}
}
@FunctionalInterface
public interface Handler {
void handle(Object o);
}
public class CustomHandler implements Handler {
@Override
public void handle(Object o) {
System.out.println("It works !");
}
}
public class TestFailure {
public static void main (String... arg){
ConcreteClass cc = new ConcreteClass();
//Grab the parent handler
// ^^^^^^^^^^^^^^
cc.setLocalHandler(cc.getHandler()::handle);
//Try to handle ==> fails
cc.check();
}
}
public class TestWorkaround {
public static void main (String... arg){
ConcreteClass cc = new ConcreteClass();
//Grab the parent handler
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
cc.setLocalHandler(cc.getForcedHandler()::handle);
//Try to handle ==> Success due to getForcedHandler() method with static type
cc.check();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Create a method that returns a static type instead of the generic one returned by parent class
public CustomHandler getForcedHandler() {
//return the parent handler
return getHandler();
}
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) Client VM (build 25.0-b70, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Windows 7 64 bits, Windows 8.1 64 bits
A DESCRIPTION OF THE PROBLEM :
Method references cannot be used with method taht returns generic type.
^^^^^^^^^^^^
getObject()::doSomething
The getObject could not be resolved if it returns a generic type
When a parent class defines a generic type with a getter.
This getter cannot be called from a child class with a method reference.
Althought if we create a new getter with the right forced type the method is correctly called.
Provided sample code reproduced the problem
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run TestFailure class
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The handler defined into AbstractClass is correctly resolved and called
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
Exception Details:
Location:
TestFailure.main([Ljava/lang/String;)V @13: invokedynamic
Reason:
Type 'Handler' (current frame, stack[1]) is not assignable to 'CustomHandler'
Current Frame:
bci: @13
flags: { }
locals: { '[Ljava/lang/String;', 'ConcreteClass' }
stack: { 'ConcreteClass', 'Handler' }
Bytecode:
0000000: bb00 1059 b700 124c 2b2b b600 13ba 001a
0000010: 0000 b600 1b2b b600 1fb1
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 ----------
// Define the generic handler
public abstract class AbstractClass <H extends Handler >{
private H parentHandler;
public AbstractClass(H parentHandler) {
super();
this.parentHandler = parentHandler;
}
public H getHandler() {
return parentHandler;
}
}
//Call the generic handler
public class ConcreteClass extends AbstractClass<CustomHandler> {
private Handler localHandler;
public ConcreteClass() {
//Define parentHandler
super(new CustomHandler());
}
public void setLocalHandler(Handler handler){
this.localHandler = handler;
}
public CustomHandler getForcedHandler() {
//return the parent handler
return getHandler();
}
public void check() {
localHandler.handle(new Object());
}
}
@FunctionalInterface
public interface Handler {
void handle(Object o);
}
public class CustomHandler implements Handler {
@Override
public void handle(Object o) {
System.out.println("It works !");
}
}
public class TestFailure {
public static void main (String... arg){
ConcreteClass cc = new ConcreteClass();
//Grab the parent handler
// ^^^^^^^^^^^^^^
cc.setLocalHandler(cc.getHandler()::handle);
//Try to handle ==> fails
cc.check();
}
}
public class TestWorkaround {
public static void main (String... arg){
ConcreteClass cc = new ConcreteClass();
//Grab the parent handler
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
cc.setLocalHandler(cc.getForcedHandler()::handle);
//Try to handle ==> Success due to getForcedHandler() method with static type
cc.check();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Create a method that returns a static type instead of the generic one returned by parent class
public CustomHandler getForcedHandler() {
//return the parent handler
return getHandler();
}
- backported by
-
JDK-8042422 Method references are broken with method that returns a generic type
-
- Closed
-