Java Casting: Java 11 throws LambdaConversionException while 1.8 does notIs Java “pass-by-reference” or “pass-by-value”?How do I efficiently iterate over each entry in a Java Map?Does a finally block always get executed in Java?How does the Java 'for each' loop work?What is the difference between public, protected, package-private and private in Java?How do I read / convert an InputStream into a String in Java?When to use LinkedList over ArrayList in Java?How do I generate random integers within a specific range in Java?Does Java support default parameter values?Why don't Java's +=, -=, *=, /= compound assignment operators require casting?

How to source a part of a file

Mortgage Pre-approval / Loan - Apply Alone or with Fiancée?

Uncaught TypeError: 'set' on proxy: trap returned falsish for property Name

Question on branch cuts and branch points

Paid for article while in US on F-1 visa?

Can a monk's single staff be considered dual wielded, as per the Dual Wielder feat?

Modeling an IP Address

Are the number of citations and number of published articles the most important criteria for a tenure promotion?

What's the point of deactivating Num Lock on login screens?

Revoked SSL certificate

Approximately how much travel time was saved by the opening of the Suez Canal in 1869?

Perform and show arithmetic with LuaLaTeX

Is it possible to run Internet Explorer on OS X El Capitan?

Does detail obscure or enhance action?

"You are your self first supporter", a more proper way to say it

Why is 150k or 200k jobs considered good when there's 300k+ births a month?

Can I make popcorn with any corn?

Why doesn't H₄O²⁺ exist?

Did Shadowfax go to Valinor?

Mutually beneficial digestive system symbiotes

Roll the carpet

Was any UN Security Council vote triple-vetoed?

Can a vampire attack twice with their claws using multiattack?

Is it inappropriate for a student to attend their mentor's dissertation defense?



Java Casting: Java 11 throws LambdaConversionException while 1.8 does not


Is Java “pass-by-reference” or “pass-by-value”?How do I efficiently iterate over each entry in a Java Map?Does a finally block always get executed in Java?How does the Java 'for each' loop work?What is the difference between public, protected, package-private and private in Java?How do I read / convert an InputStream into a String in Java?When to use LinkedList over ArrayList in Java?How do I generate random integers within a specific range in Java?Does Java support default parameter values?Why don't Java's +=, -=, *=, /= compound assignment operators require casting?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








39















the following code works perfectly fine in a Java 1.8 VM but produces a LambdaConversionException when executed in a Java 11 VM. Wheres the difference and why does it behave like this?




Code:



public void addSomeListener(Component comp)
if(comp instanceof HasValue)
((HasValue<?,?>) comp).addValueChangeListener(evt ->
//do sth with evt
);




HasValue Javadoc



Exception (V11 only):



Caused by: java.lang.invoke.LambdaConversionException: Type mismatch
for instantiated parameter 0: class java.lang.Object is not a subtype
of interface com.vaadin.flow.component.HasValue$ValueChangeEvent
at java.base/java.lang.invoke.AbstractValidatingLambdaMetafactory.checkDescriptor(AbstractValidatingLambdaMetafactory.java:308)
at java.base/java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:294)
at java.base/java.lang.invoke.LambdaMetafactory.altMetafactory(LambdaMetafactory.java:503)
at java.base/java.lang.invoke.BootstrapMethodInvoker.invoke(BootstrapMethodInvoker.java:138)
... 73 more



Workaround:



ValueChangeListener<ValueChangeEvent<?>> listener = evt -> 
// do sth with evt
;
((HasValue<?,?>) comp).addValueChangeListener(listener);



System:

OS: Windows 10

IDE: Eclipse 2018-12 (4.10.0)

Java (Compile): JDK 1.8.0_201

Java (Webserver): JDK 11.0.2

Webserver: Wildfly 15










share|improve this question



















  • 2





    Interesting and yet poor thing there (HasValue<?,?>) comp ... Such validation though agreed didn't exist in the JDK-8 code.

    – Naman
    11 hours ago












  • When exactly do you get this exception? When you add the listener or when the listener is invoked with an event? If the latter, how do you invoke it with an event (show the code place)

    – Erwin Bolwidt
    11 hours ago






  • 6





    That’s an important information, as Eclipse has its own compiler, so problems caused by the compiler (and this looks much like a compiler problem) do not have to apply to javac then.

    – Holger
    10 hours ago






  • 2





    @JornVernee changing the language level sometimes causes behavioral changes in the compiler.

    – Holger
    9 hours ago






  • 1





    @CommonMan IJ neither has its own compiler nor is it a Java VM, so it makes no difference in this case whether you write your code with IJ or a text editor.

    – howlger
    9 hours ago

















39















the following code works perfectly fine in a Java 1.8 VM but produces a LambdaConversionException when executed in a Java 11 VM. Wheres the difference and why does it behave like this?




Code:



public void addSomeListener(Component comp)
if(comp instanceof HasValue)
((HasValue<?,?>) comp).addValueChangeListener(evt ->
//do sth with evt
);




HasValue Javadoc



Exception (V11 only):



Caused by: java.lang.invoke.LambdaConversionException: Type mismatch
for instantiated parameter 0: class java.lang.Object is not a subtype
of interface com.vaadin.flow.component.HasValue$ValueChangeEvent
at java.base/java.lang.invoke.AbstractValidatingLambdaMetafactory.checkDescriptor(AbstractValidatingLambdaMetafactory.java:308)
at java.base/java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:294)
at java.base/java.lang.invoke.LambdaMetafactory.altMetafactory(LambdaMetafactory.java:503)
at java.base/java.lang.invoke.BootstrapMethodInvoker.invoke(BootstrapMethodInvoker.java:138)
... 73 more



Workaround:



ValueChangeListener<ValueChangeEvent<?>> listener = evt -> 
// do sth with evt
;
((HasValue<?,?>) comp).addValueChangeListener(listener);



System:

OS: Windows 10

IDE: Eclipse 2018-12 (4.10.0)

Java (Compile): JDK 1.8.0_201

Java (Webserver): JDK 11.0.2

Webserver: Wildfly 15










share|improve this question



















  • 2





    Interesting and yet poor thing there (HasValue<?,?>) comp ... Such validation though agreed didn't exist in the JDK-8 code.

    – Naman
    11 hours ago












  • When exactly do you get this exception? When you add the listener or when the listener is invoked with an event? If the latter, how do you invoke it with an event (show the code place)

    – Erwin Bolwidt
    11 hours ago






  • 6





    That’s an important information, as Eclipse has its own compiler, so problems caused by the compiler (and this looks much like a compiler problem) do not have to apply to javac then.

    – Holger
    10 hours ago






  • 2





    @JornVernee changing the language level sometimes causes behavioral changes in the compiler.

    – Holger
    9 hours ago






  • 1





    @CommonMan IJ neither has its own compiler nor is it a Java VM, so it makes no difference in this case whether you write your code with IJ or a text editor.

    – howlger
    9 hours ago













39












39








39


9






the following code works perfectly fine in a Java 1.8 VM but produces a LambdaConversionException when executed in a Java 11 VM. Wheres the difference and why does it behave like this?




Code:



public void addSomeListener(Component comp)
if(comp instanceof HasValue)
((HasValue<?,?>) comp).addValueChangeListener(evt ->
//do sth with evt
);




HasValue Javadoc



Exception (V11 only):



Caused by: java.lang.invoke.LambdaConversionException: Type mismatch
for instantiated parameter 0: class java.lang.Object is not a subtype
of interface com.vaadin.flow.component.HasValue$ValueChangeEvent
at java.base/java.lang.invoke.AbstractValidatingLambdaMetafactory.checkDescriptor(AbstractValidatingLambdaMetafactory.java:308)
at java.base/java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:294)
at java.base/java.lang.invoke.LambdaMetafactory.altMetafactory(LambdaMetafactory.java:503)
at java.base/java.lang.invoke.BootstrapMethodInvoker.invoke(BootstrapMethodInvoker.java:138)
... 73 more



Workaround:



ValueChangeListener<ValueChangeEvent<?>> listener = evt -> 
// do sth with evt
;
((HasValue<?,?>) comp).addValueChangeListener(listener);



System:

OS: Windows 10

IDE: Eclipse 2018-12 (4.10.0)

Java (Compile): JDK 1.8.0_201

Java (Webserver): JDK 11.0.2

Webserver: Wildfly 15










share|improve this question
















the following code works perfectly fine in a Java 1.8 VM but produces a LambdaConversionException when executed in a Java 11 VM. Wheres the difference and why does it behave like this?




Code:



public void addSomeListener(Component comp)
if(comp instanceof HasValue)
((HasValue<?,?>) comp).addValueChangeListener(evt ->
//do sth with evt
);




HasValue Javadoc



Exception (V11 only):



Caused by: java.lang.invoke.LambdaConversionException: Type mismatch
for instantiated parameter 0: class java.lang.Object is not a subtype
of interface com.vaadin.flow.component.HasValue$ValueChangeEvent
at java.base/java.lang.invoke.AbstractValidatingLambdaMetafactory.checkDescriptor(AbstractValidatingLambdaMetafactory.java:308)
at java.base/java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:294)
at java.base/java.lang.invoke.LambdaMetafactory.altMetafactory(LambdaMetafactory.java:503)
at java.base/java.lang.invoke.BootstrapMethodInvoker.invoke(BootstrapMethodInvoker.java:138)
... 73 more



Workaround:



ValueChangeListener<ValueChangeEvent<?>> listener = evt -> 
// do sth with evt
;
((HasValue<?,?>) comp).addValueChangeListener(listener);



System:

OS: Windows 10

IDE: Eclipse 2018-12 (4.10.0)

Java (Compile): JDK 1.8.0_201

Java (Webserver): JDK 11.0.2

Webserver: Wildfly 15







java eclipse java-8 java-11 vaadin-flow






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 7 hours ago







Gerrit Sedlaczek

















asked 11 hours ago









Gerrit SedlaczekGerrit Sedlaczek

5121616




5121616







  • 2





    Interesting and yet poor thing there (HasValue<?,?>) comp ... Such validation though agreed didn't exist in the JDK-8 code.

    – Naman
    11 hours ago












  • When exactly do you get this exception? When you add the listener or when the listener is invoked with an event? If the latter, how do you invoke it with an event (show the code place)

    – Erwin Bolwidt
    11 hours ago






  • 6





    That’s an important information, as Eclipse has its own compiler, so problems caused by the compiler (and this looks much like a compiler problem) do not have to apply to javac then.

    – Holger
    10 hours ago






  • 2





    @JornVernee changing the language level sometimes causes behavioral changes in the compiler.

    – Holger
    9 hours ago






  • 1





    @CommonMan IJ neither has its own compiler nor is it a Java VM, so it makes no difference in this case whether you write your code with IJ or a text editor.

    – howlger
    9 hours ago












  • 2





    Interesting and yet poor thing there (HasValue<?,?>) comp ... Such validation though agreed didn't exist in the JDK-8 code.

    – Naman
    11 hours ago












  • When exactly do you get this exception? When you add the listener or when the listener is invoked with an event? If the latter, how do you invoke it with an event (show the code place)

    – Erwin Bolwidt
    11 hours ago






  • 6





    That’s an important information, as Eclipse has its own compiler, so problems caused by the compiler (and this looks much like a compiler problem) do not have to apply to javac then.

    – Holger
    10 hours ago






  • 2





    @JornVernee changing the language level sometimes causes behavioral changes in the compiler.

    – Holger
    9 hours ago






  • 1





    @CommonMan IJ neither has its own compiler nor is it a Java VM, so it makes no difference in this case whether you write your code with IJ or a text editor.

    – howlger
    9 hours ago







2




2





Interesting and yet poor thing there (HasValue<?,?>) comp ... Such validation though agreed didn't exist in the JDK-8 code.

– Naman
11 hours ago






Interesting and yet poor thing there (HasValue<?,?>) comp ... Such validation though agreed didn't exist in the JDK-8 code.

– Naman
11 hours ago














When exactly do you get this exception? When you add the listener or when the listener is invoked with an event? If the latter, how do you invoke it with an event (show the code place)

– Erwin Bolwidt
11 hours ago





When exactly do you get this exception? When you add the listener or when the listener is invoked with an event? If the latter, how do you invoke it with an event (show the code place)

– Erwin Bolwidt
11 hours ago




6




6





That’s an important information, as Eclipse has its own compiler, so problems caused by the compiler (and this looks much like a compiler problem) do not have to apply to javac then.

– Holger
10 hours ago





That’s an important information, as Eclipse has its own compiler, so problems caused by the compiler (and this looks much like a compiler problem) do not have to apply to javac then.

– Holger
10 hours ago




2




2





@JornVernee changing the language level sometimes causes behavioral changes in the compiler.

– Holger
9 hours ago





@JornVernee changing the language level sometimes causes behavioral changes in the compiler.

– Holger
9 hours ago




1




1





@CommonMan IJ neither has its own compiler nor is it a Java VM, so it makes no difference in this case whether you write your code with IJ or a text editor.

– howlger
9 hours ago





@CommonMan IJ neither has its own compiler nor is it a Java VM, so it makes no difference in this case whether you write your code with IJ or a text editor.

– howlger
9 hours ago












1 Answer
1






active

oldest

votes


















29














TL;DR The Eclipse compiler generates a method signature for the lambda instance that is invalid according to the specification. Due to additional type checking code added in JDK 9 to better enforce the specification, the incorrect signature is now causing an exception when running on Java 11.




Verified with Eclipse 2019-03 as well with this code:



public class Main 
public static void main(String[] args)
getHasValue().addValueChangeListener(evt -> );


public static HasValue<?, ?> getHasValue()
return null;



interface HasValue<E extends HasValue.ValueChangeEvent<V>,V>
public static interface ValueChangeEvent<V>
public static interface ValueChangeListener<E extends HasValue.ValueChangeEvent<?>>
void valueChanged(E event);

void addValueChangeListener(HasValue.ValueChangeListener<? super E> listener);



Even when using null as the receiver, the code fails when bootstrapping with the same error.



Using javap -v Main we can see where the problem lies. I'm seeing this in the BoostrapMethods table:



BootstrapMethods:
0: #48 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
#50 (Lmain/HasValue$ValueChangeEvent;)V
#53 REF_invokeStatic main/Main.lambda$0:(Ljava/lang/Object;)V
#54 (Ljava/lang/Object;)V


Note that the last argument (constant #54) is (Ljava/lang/Object;)V, while javac generates (Lmain/HasValue$ValueChangeEvent;)V. i.e. the method signature that Eclipse wants to use for the lambda is different from what javac wants to use.



If the wanted method signature is the erasure of the target method (which seems to be the case), then the correct method signature is indeed (Lmain/HasValue$ValueChangeEvent;)V since that is the erasure of the target method, which is:



void valueChanged(E event);


Where E is E extends HasValue.ValueChangeEvent<?>, so that would be erased to HasValue.ValueChangeEvent.



The problem seems to be with ECJ, and seems to have been brought to the surface by JDK-8173587 (revision) (Unfortunately this seems to be a private ticket.) which adds extra type checks to verify that the SAM method type is actually compatible with the instantiate method type. According to the documentation of LambdaMetafactory::metafactory the instantiated method type must be the same, or a specialization of the SAM method type:




instantiatedMethodType - The signature and return type that should be enforced dynamically at invocation time. This may be the same as samMethodType, or may be a specialization of it.




which the method type generated by ECJ is evidently not, so this ends up throwing an exception. (though, to be fair, I don't see defined anywhere what constitutes a "specialization" in this case). I've reported this on the Eclipse bugzilla here: https://bugs.eclipse.org/bugs/show_bug.cgi?id=546161



I'm guessing this change was made somewhere in JDK 9, since source code was already modular at that point, and the date of the revision is fairly early (February 2017).



Since javac generates the correct method signature, you could switch to that for the time being as a workaround.






share|improve this answer




















  • 7





    I tend to over-complicate these bytecode related answers (being someone who's used to looking at bytecode). It's hard to find the right balance between sufficient explanation, and keeping the answer succinct. If anything is unclear, please feel free to ask for clarification.

    – Jorn Vernee
    8 hours ago











  • this is not over-complicate and it's an easy to read and understand answer, there simply isn't a better one. I had a pleasure reading it, thank you for taking the time

    – Eugene
    7 hours ago











  • Could you please add a link to the corresponding Eclipse bug?

    – howlger
    7 hours ago











  • @JornVernee Not at all. I think you explain bytecode related answers very well.

    – Michael Berry
    7 hours ago






  • 1





    @howlger Done: bugs.eclipse.org/bugs/show_bug.cgi?id=546161

    – Jorn Vernee
    5 hours ago











Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55532055%2fjava-casting-java-11-throws-lambdaconversionexception-while-1-8-does-not%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









29














TL;DR The Eclipse compiler generates a method signature for the lambda instance that is invalid according to the specification. Due to additional type checking code added in JDK 9 to better enforce the specification, the incorrect signature is now causing an exception when running on Java 11.




Verified with Eclipse 2019-03 as well with this code:



public class Main 
public static void main(String[] args)
getHasValue().addValueChangeListener(evt -> );


public static HasValue<?, ?> getHasValue()
return null;



interface HasValue<E extends HasValue.ValueChangeEvent<V>,V>
public static interface ValueChangeEvent<V>
public static interface ValueChangeListener<E extends HasValue.ValueChangeEvent<?>>
void valueChanged(E event);

void addValueChangeListener(HasValue.ValueChangeListener<? super E> listener);



Even when using null as the receiver, the code fails when bootstrapping with the same error.



Using javap -v Main we can see where the problem lies. I'm seeing this in the BoostrapMethods table:



BootstrapMethods:
0: #48 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
#50 (Lmain/HasValue$ValueChangeEvent;)V
#53 REF_invokeStatic main/Main.lambda$0:(Ljava/lang/Object;)V
#54 (Ljava/lang/Object;)V


Note that the last argument (constant #54) is (Ljava/lang/Object;)V, while javac generates (Lmain/HasValue$ValueChangeEvent;)V. i.e. the method signature that Eclipse wants to use for the lambda is different from what javac wants to use.



If the wanted method signature is the erasure of the target method (which seems to be the case), then the correct method signature is indeed (Lmain/HasValue$ValueChangeEvent;)V since that is the erasure of the target method, which is:



void valueChanged(E event);


Where E is E extends HasValue.ValueChangeEvent<?>, so that would be erased to HasValue.ValueChangeEvent.



The problem seems to be with ECJ, and seems to have been brought to the surface by JDK-8173587 (revision) (Unfortunately this seems to be a private ticket.) which adds extra type checks to verify that the SAM method type is actually compatible with the instantiate method type. According to the documentation of LambdaMetafactory::metafactory the instantiated method type must be the same, or a specialization of the SAM method type:




instantiatedMethodType - The signature and return type that should be enforced dynamically at invocation time. This may be the same as samMethodType, or may be a specialization of it.




which the method type generated by ECJ is evidently not, so this ends up throwing an exception. (though, to be fair, I don't see defined anywhere what constitutes a "specialization" in this case). I've reported this on the Eclipse bugzilla here: https://bugs.eclipse.org/bugs/show_bug.cgi?id=546161



I'm guessing this change was made somewhere in JDK 9, since source code was already modular at that point, and the date of the revision is fairly early (February 2017).



Since javac generates the correct method signature, you could switch to that for the time being as a workaround.






share|improve this answer




















  • 7





    I tend to over-complicate these bytecode related answers (being someone who's used to looking at bytecode). It's hard to find the right balance between sufficient explanation, and keeping the answer succinct. If anything is unclear, please feel free to ask for clarification.

    – Jorn Vernee
    8 hours ago











  • this is not over-complicate and it's an easy to read and understand answer, there simply isn't a better one. I had a pleasure reading it, thank you for taking the time

    – Eugene
    7 hours ago











  • Could you please add a link to the corresponding Eclipse bug?

    – howlger
    7 hours ago











  • @JornVernee Not at all. I think you explain bytecode related answers very well.

    – Michael Berry
    7 hours ago






  • 1





    @howlger Done: bugs.eclipse.org/bugs/show_bug.cgi?id=546161

    – Jorn Vernee
    5 hours ago















29














TL;DR The Eclipse compiler generates a method signature for the lambda instance that is invalid according to the specification. Due to additional type checking code added in JDK 9 to better enforce the specification, the incorrect signature is now causing an exception when running on Java 11.




Verified with Eclipse 2019-03 as well with this code:



public class Main 
public static void main(String[] args)
getHasValue().addValueChangeListener(evt -> );


public static HasValue<?, ?> getHasValue()
return null;



interface HasValue<E extends HasValue.ValueChangeEvent<V>,V>
public static interface ValueChangeEvent<V>
public static interface ValueChangeListener<E extends HasValue.ValueChangeEvent<?>>
void valueChanged(E event);

void addValueChangeListener(HasValue.ValueChangeListener<? super E> listener);



Even when using null as the receiver, the code fails when bootstrapping with the same error.



Using javap -v Main we can see where the problem lies. I'm seeing this in the BoostrapMethods table:



BootstrapMethods:
0: #48 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
#50 (Lmain/HasValue$ValueChangeEvent;)V
#53 REF_invokeStatic main/Main.lambda$0:(Ljava/lang/Object;)V
#54 (Ljava/lang/Object;)V


Note that the last argument (constant #54) is (Ljava/lang/Object;)V, while javac generates (Lmain/HasValue$ValueChangeEvent;)V. i.e. the method signature that Eclipse wants to use for the lambda is different from what javac wants to use.



If the wanted method signature is the erasure of the target method (which seems to be the case), then the correct method signature is indeed (Lmain/HasValue$ValueChangeEvent;)V since that is the erasure of the target method, which is:



void valueChanged(E event);


Where E is E extends HasValue.ValueChangeEvent<?>, so that would be erased to HasValue.ValueChangeEvent.



The problem seems to be with ECJ, and seems to have been brought to the surface by JDK-8173587 (revision) (Unfortunately this seems to be a private ticket.) which adds extra type checks to verify that the SAM method type is actually compatible with the instantiate method type. According to the documentation of LambdaMetafactory::metafactory the instantiated method type must be the same, or a specialization of the SAM method type:




instantiatedMethodType - The signature and return type that should be enforced dynamically at invocation time. This may be the same as samMethodType, or may be a specialization of it.




which the method type generated by ECJ is evidently not, so this ends up throwing an exception. (though, to be fair, I don't see defined anywhere what constitutes a "specialization" in this case). I've reported this on the Eclipse bugzilla here: https://bugs.eclipse.org/bugs/show_bug.cgi?id=546161



I'm guessing this change was made somewhere in JDK 9, since source code was already modular at that point, and the date of the revision is fairly early (February 2017).



Since javac generates the correct method signature, you could switch to that for the time being as a workaround.






share|improve this answer




















  • 7





    I tend to over-complicate these bytecode related answers (being someone who's used to looking at bytecode). It's hard to find the right balance between sufficient explanation, and keeping the answer succinct. If anything is unclear, please feel free to ask for clarification.

    – Jorn Vernee
    8 hours ago











  • this is not over-complicate and it's an easy to read and understand answer, there simply isn't a better one. I had a pleasure reading it, thank you for taking the time

    – Eugene
    7 hours ago











  • Could you please add a link to the corresponding Eclipse bug?

    – howlger
    7 hours ago











  • @JornVernee Not at all. I think you explain bytecode related answers very well.

    – Michael Berry
    7 hours ago






  • 1





    @howlger Done: bugs.eclipse.org/bugs/show_bug.cgi?id=546161

    – Jorn Vernee
    5 hours ago













29












29








29







TL;DR The Eclipse compiler generates a method signature for the lambda instance that is invalid according to the specification. Due to additional type checking code added in JDK 9 to better enforce the specification, the incorrect signature is now causing an exception when running on Java 11.




Verified with Eclipse 2019-03 as well with this code:



public class Main 
public static void main(String[] args)
getHasValue().addValueChangeListener(evt -> );


public static HasValue<?, ?> getHasValue()
return null;



interface HasValue<E extends HasValue.ValueChangeEvent<V>,V>
public static interface ValueChangeEvent<V>
public static interface ValueChangeListener<E extends HasValue.ValueChangeEvent<?>>
void valueChanged(E event);

void addValueChangeListener(HasValue.ValueChangeListener<? super E> listener);



Even when using null as the receiver, the code fails when bootstrapping with the same error.



Using javap -v Main we can see where the problem lies. I'm seeing this in the BoostrapMethods table:



BootstrapMethods:
0: #48 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
#50 (Lmain/HasValue$ValueChangeEvent;)V
#53 REF_invokeStatic main/Main.lambda$0:(Ljava/lang/Object;)V
#54 (Ljava/lang/Object;)V


Note that the last argument (constant #54) is (Ljava/lang/Object;)V, while javac generates (Lmain/HasValue$ValueChangeEvent;)V. i.e. the method signature that Eclipse wants to use for the lambda is different from what javac wants to use.



If the wanted method signature is the erasure of the target method (which seems to be the case), then the correct method signature is indeed (Lmain/HasValue$ValueChangeEvent;)V since that is the erasure of the target method, which is:



void valueChanged(E event);


Where E is E extends HasValue.ValueChangeEvent<?>, so that would be erased to HasValue.ValueChangeEvent.



The problem seems to be with ECJ, and seems to have been brought to the surface by JDK-8173587 (revision) (Unfortunately this seems to be a private ticket.) which adds extra type checks to verify that the SAM method type is actually compatible with the instantiate method type. According to the documentation of LambdaMetafactory::metafactory the instantiated method type must be the same, or a specialization of the SAM method type:




instantiatedMethodType - The signature and return type that should be enforced dynamically at invocation time. This may be the same as samMethodType, or may be a specialization of it.




which the method type generated by ECJ is evidently not, so this ends up throwing an exception. (though, to be fair, I don't see defined anywhere what constitutes a "specialization" in this case). I've reported this on the Eclipse bugzilla here: https://bugs.eclipse.org/bugs/show_bug.cgi?id=546161



I'm guessing this change was made somewhere in JDK 9, since source code was already modular at that point, and the date of the revision is fairly early (February 2017).



Since javac generates the correct method signature, you could switch to that for the time being as a workaround.






share|improve this answer















TL;DR The Eclipse compiler generates a method signature for the lambda instance that is invalid according to the specification. Due to additional type checking code added in JDK 9 to better enforce the specification, the incorrect signature is now causing an exception when running on Java 11.




Verified with Eclipse 2019-03 as well with this code:



public class Main 
public static void main(String[] args)
getHasValue().addValueChangeListener(evt -> );


public static HasValue<?, ?> getHasValue()
return null;



interface HasValue<E extends HasValue.ValueChangeEvent<V>,V>
public static interface ValueChangeEvent<V>
public static interface ValueChangeListener<E extends HasValue.ValueChangeEvent<?>>
void valueChanged(E event);

void addValueChangeListener(HasValue.ValueChangeListener<? super E> listener);



Even when using null as the receiver, the code fails when bootstrapping with the same error.



Using javap -v Main we can see where the problem lies. I'm seeing this in the BoostrapMethods table:



BootstrapMethods:
0: #48 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
#50 (Lmain/HasValue$ValueChangeEvent;)V
#53 REF_invokeStatic main/Main.lambda$0:(Ljava/lang/Object;)V
#54 (Ljava/lang/Object;)V


Note that the last argument (constant #54) is (Ljava/lang/Object;)V, while javac generates (Lmain/HasValue$ValueChangeEvent;)V. i.e. the method signature that Eclipse wants to use for the lambda is different from what javac wants to use.



If the wanted method signature is the erasure of the target method (which seems to be the case), then the correct method signature is indeed (Lmain/HasValue$ValueChangeEvent;)V since that is the erasure of the target method, which is:



void valueChanged(E event);


Where E is E extends HasValue.ValueChangeEvent<?>, so that would be erased to HasValue.ValueChangeEvent.



The problem seems to be with ECJ, and seems to have been brought to the surface by JDK-8173587 (revision) (Unfortunately this seems to be a private ticket.) which adds extra type checks to verify that the SAM method type is actually compatible with the instantiate method type. According to the documentation of LambdaMetafactory::metafactory the instantiated method type must be the same, or a specialization of the SAM method type:




instantiatedMethodType - The signature and return type that should be enforced dynamically at invocation time. This may be the same as samMethodType, or may be a specialization of it.




which the method type generated by ECJ is evidently not, so this ends up throwing an exception. (though, to be fair, I don't see defined anywhere what constitutes a "specialization" in this case). I've reported this on the Eclipse bugzilla here: https://bugs.eclipse.org/bugs/show_bug.cgi?id=546161



I'm guessing this change was made somewhere in JDK 9, since source code was already modular at that point, and the date of the revision is fairly early (February 2017).



Since javac generates the correct method signature, you could switch to that for the time being as a workaround.







share|improve this answer














share|improve this answer



share|improve this answer








edited 5 hours ago

























answered 9 hours ago









Jorn VerneeJorn Vernee

21.2k34265




21.2k34265







  • 7





    I tend to over-complicate these bytecode related answers (being someone who's used to looking at bytecode). It's hard to find the right balance between sufficient explanation, and keeping the answer succinct. If anything is unclear, please feel free to ask for clarification.

    – Jorn Vernee
    8 hours ago











  • this is not over-complicate and it's an easy to read and understand answer, there simply isn't a better one. I had a pleasure reading it, thank you for taking the time

    – Eugene
    7 hours ago











  • Could you please add a link to the corresponding Eclipse bug?

    – howlger
    7 hours ago











  • @JornVernee Not at all. I think you explain bytecode related answers very well.

    – Michael Berry
    7 hours ago






  • 1





    @howlger Done: bugs.eclipse.org/bugs/show_bug.cgi?id=546161

    – Jorn Vernee
    5 hours ago












  • 7





    I tend to over-complicate these bytecode related answers (being someone who's used to looking at bytecode). It's hard to find the right balance between sufficient explanation, and keeping the answer succinct. If anything is unclear, please feel free to ask for clarification.

    – Jorn Vernee
    8 hours ago











  • this is not over-complicate and it's an easy to read and understand answer, there simply isn't a better one. I had a pleasure reading it, thank you for taking the time

    – Eugene
    7 hours ago











  • Could you please add a link to the corresponding Eclipse bug?

    – howlger
    7 hours ago











  • @JornVernee Not at all. I think you explain bytecode related answers very well.

    – Michael Berry
    7 hours ago






  • 1





    @howlger Done: bugs.eclipse.org/bugs/show_bug.cgi?id=546161

    – Jorn Vernee
    5 hours ago







7




7





I tend to over-complicate these bytecode related answers (being someone who's used to looking at bytecode). It's hard to find the right balance between sufficient explanation, and keeping the answer succinct. If anything is unclear, please feel free to ask for clarification.

– Jorn Vernee
8 hours ago





I tend to over-complicate these bytecode related answers (being someone who's used to looking at bytecode). It's hard to find the right balance between sufficient explanation, and keeping the answer succinct. If anything is unclear, please feel free to ask for clarification.

– Jorn Vernee
8 hours ago













this is not over-complicate and it's an easy to read and understand answer, there simply isn't a better one. I had a pleasure reading it, thank you for taking the time

– Eugene
7 hours ago





this is not over-complicate and it's an easy to read and understand answer, there simply isn't a better one. I had a pleasure reading it, thank you for taking the time

– Eugene
7 hours ago













Could you please add a link to the corresponding Eclipse bug?

– howlger
7 hours ago





Could you please add a link to the corresponding Eclipse bug?

– howlger
7 hours ago













@JornVernee Not at all. I think you explain bytecode related answers very well.

– Michael Berry
7 hours ago





@JornVernee Not at all. I think you explain bytecode related answers very well.

– Michael Berry
7 hours ago




1




1





@howlger Done: bugs.eclipse.org/bugs/show_bug.cgi?id=546161

– Jorn Vernee
5 hours ago





@howlger Done: bugs.eclipse.org/bugs/show_bug.cgi?id=546161

– Jorn Vernee
5 hours ago



















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55532055%2fjava-casting-java-11-throws-lambdaconversionexception-while-1-8-does-not%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Category:Fedor von Bock Media in category "Fedor von Bock"Navigation menuUpload mediaISNI: 0000 0000 5511 3417VIAF ID: 24712551GND ID: 119294796Library of Congress authority ID: n96068363BnF ID: 12534305fSUDOC authorities ID: 034604189Open Library ID: OL338253ANKCR AUT ID: jn19990000869National Library of Israel ID: 000514068National Thesaurus for Author Names ID: 341574317ReasonatorScholiaStatistics

Reverse int within the 32-bit signed integer range: [−2^31, 2^31 − 1]Combining two 32-bit integers into one 64-bit integerDetermine if an int is within rangeLossy packing 32 bit integer to 16 bitComputing the square root of a 64-bit integerKeeping integer addition within boundsSafe multiplication of two 64-bit signed integersLeetcode 10: Regular Expression MatchingSigned integer-to-ascii x86_64 assembler macroReverse the digits of an Integer“Add two numbers given in reverse order from a linked list”

Kiel Indholdsfortegnelse Historie | Transport og færgeforbindelser | Sejlsport og anden sport | Kultur | Kendte personer fra Kiel | Noter | Litteratur | Eksterne henvisninger | Navigationsmenuwww.kiel.de54°19′31″N 10°8′26″Ø / 54.32528°N 10.14056°Ø / 54.32528; 10.14056Oberbürgermeister Dr. Ulf Kämpferwww.statistik-nord.deDen danske Stats StatistikKiels hjemmesiderrrWorldCat312794080n790547494030481-4