Why method reference produces java.lang.BootstrapMethodError [duplicate] - java

I have some code with a method reference that compiles fine and fails at runtime.
The exception is this:
Caused by: java.lang.invoke.LambdaConversionException: Invalid receiver type class redacted.BasicEntity; not a subtype of implementation type interface redacted.HasImagesEntity
at java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:233)
at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:303)
at java.lang.invoke.CallSite.makeSite(CallSite.java:289)
The class triggering the exception:
class ImageController<E extends BasicEntity & HasImagesEntity> {
void doTheThing(E entity) {
Set<String> filenames = entity.getImages().keySet().stream()
.map(entity::filename)
.collect(Collectors.toSet());
}
}
The exception is thrown trying to resolve entity::filename. filename() is declared in HasImagesEntity. As far as I can tell, I get the exception because the erasure of E is BasicEntity and the JVM doesn't (can't?) consider other bounds on E.
When I rewrite the method reference as a trivial lambda, everything is fine. It seems really fishy to me that one construct works as expected and its semantic equivalent blows up.
Could this possibly be in the spec? I'm trying very hard to find a way for this not to be a problem in the compiler or runtime, and haven't come up with anything.

Here is a simplified example which reproduces the problem and uses only core Java classes:
public static void main(String[] argv) {
System.out.println(dummy("foo"));
}
static <T extends Serializable&CharSequence> int dummy(T value) {
return Optional.ofNullable(value).map(CharSequence::length).orElse(0);
}
Your assumption is correct, the JRE-specific implementation receives the target method as a MethodHandle which has no information about generic types. Therefore the only thing it sees is that the raw types mismatch.
Like with a lot of generic constructs, there is a type cast required on the byte code level which doesn’t appear in the source code. Since LambdaMetafactory explicitly requires a direct method handle, a method reference which encapsulates such a type cast cannot be passed as a MethodHandle to the factory.
There are two possible ways to deal with it.
First solution would be to change the LambdaMetafactory to trust the MethodHandle if the receiver type is an interface and insert the required type cast by itself in the generated lambda class instead of rejecting it. After all, it does similar for parameter and return types already.
Alternatively, the compiler would be in charge to create a synthetic helper method encapsulating the type cast and method call, just like if you had written a lambda expression. This is not a unique situation. If you use a method reference to a varargs method or an array creation like, e.g. String[]::new, they can’t be expressed as direct method handles and end up in synthetic helper methods.
In either case, we can consider the current behavior a bug. But obviously, compiler and JRE developers must agree on which way it should be handled before we can say on which side the bug resides.

I've just fixed this issue in JDK9 and JDK8u45. See this bug. The change will take a little while to percolate into promoted builds.
Dan just pointed me at this Stack Overflow question, so I'm adding this note When you find bugs, please do submit them.
I addressed this by having the compiler create a bridge, as is the approach for many cases of complex method references. We are also examining spec implications.

This bug is not entirely fixed. I just ran into a LambdaConversionException in 1.8.0_72 and saw that there are open bug reports in Oracle's bug tracking system: link1, link2.
(Edit: The linked bugs are reported to be closed in JDK 9 b93)
As a simple workaround I avoid method handles. So instead of
.map(entity::filename)
I do
.map(entity -> entity.filename())
Here is the code for reproducing the problem on Debian 3.11.8-1 x86_64.
import java.awt.Component;
import java.util.Collection;
import java.util.Collections;
public class MethodHandleTest {
public static void main(String... args) {
new MethodHandleTest().run();
}
private void run() {
ComponentWithSomeMethod myComp = new ComponentWithSomeMethod();
new Caller<ComponentWithSomeMethod>().callSomeMethod(Collections.singletonList(myComp));
}
private interface HasSomeMethod {
void someMethod();
}
static class ComponentWithSomeMethod extends Component implements HasSomeMethod {
#Override
public void someMethod() {
System.out.println("Some method");
}
}
class Caller<T extends Component & HasSomeMethod> {
public void callSomeMethod(Collection<T> components) {
components.forEach(HasSomeMethod::someMethod); // <-- crashes
// components.forEach(comp -> comp.someMethod()); <-- works fine
}
}
}

I found a workaround for this was swapping the order of the generics. For instance, use class A<T extends B & C> where you need to access a B method, or use class A<T extends C & B> if you need to access a C method. Of course, if you need access to methods from both classes, this won't work. I found this useful when one of the interfaces was a marker interface like Serializable.
As for fixing this in the JDK, the only info I could find were some bugs on openjdk's bug tracker that are marked resolved in version 9 which is rather unhelpful.

For the record, the Eclipse compiler of Eclipse 2021-09 (4.21.0) still seems to have this (or a very similar) bug, which I've reported here: https://bugs.eclipse.org/bugs/show_bug.cgi?id=577466
So, if you're developing with Eclipse, it might be this error still persists when developing (using the Eclipse compiler), even when at build time, it is absent (using javac via Maven or Gradle, etc.).

Related

Check type of Predicate generic

I'm having 2 classes, their internals doesn't matter at all.
class ClassA {
//...
}
class ClassB {
//...
}
And I'm having 2 predicates that use those classes, let's say they look like this
private Predicate<ClassA> classAPredicate() {
return Objects::nonNull;
}
private Predicate<ClassB> classBPredicate() {
return Objects::nonNull;
}
Now, I'm having generic method in external library that is already beeing used by many users and unfortunatelly, it has pretty generic input parameter which is Object which in 90% of cases is Predicate.
What I need to do, is to extend this method functionality by checking type of passed Predicate and based on that, perform some operations.
public void test(Object obj) {
Predicate predicate = (Predicate)obj;
if(predicate.getClass().isAssignableFrom(ClassA.class)) {
System.out.println(predicate.test(new ClassA()));
// logic specific to Predicate<ClassA>
} else {
System.out.println(predicate.test(new ClassB()));
// logic specific to Predicate<ClassB>
}
}
But, during tests I'm passing both Predicates and it fails with Exception in thread "main" java.lang.ClassCastException:
test(classAPredicate());
test(classBPredicate());
I've been debugging and isAssignableFrom() is always returning false so the error is obvious here. I'm not sure if that is the right approach, but I didn't came up with anything else yet. Is there any way to check what is the type of that Predicate?
I know that what I'm trying to implement isn't ideal, but that is current requirement...
In the above, the predicate class is not assignable from Class A.
if(predicate.getClass().isAssignableFrom(ClassA.class))
This causes the else condition to run which passes an instance of B to the Predicate for type A which causes a cast exception. Due to type erasure, it will not be easy to resolve whether an instance of A or B should be passed to the predicate. 3 options are:
Try each input type until one doesn't throw a ClassCastException.
Handle the expected behavior in a new method instead of the existing test function.
Define a more specific interface than Predicate which also has a method to get the type the predicate tests and use the test type in the condition instead. Ex:
public interface TypedPredicate<T> extends Predicate<T> { Class<T> getTestType(); }
Well,
I have been doing Java Generics for going on three years now. I can cite a dozen Stack Overflow posts about "Reifying Java Generics" here: SO1, SO2, SO3. Most importantly, if you are intending to write Java for years and years, you must know that the "Generic Type Parameter" are simply NOT ACCESSIBLE at Run-Time without fields, or extra methods to retrieve them. Java Generics (The syntax that looks like: STUFF<TYPE> with the greater-than, less-than symbols is STRICTLY A COMPILE-TIME FEATURE). At RunTime, the JRE simply has no idea what the Type of the Type-Parameter is - and all it can do is throw ClassCastException if an attempt to misuse occurs.
NOTE: 'Misuse' the generic type such that it throws ClassCastException should sound odd if you are thinking that the JRE does not know and does not care what the type of the type parameter is. Mostly, the way exceptions are thrown, is such that if the code you write inside of a generic makes presumptions, and if it has made faulty presumptions, then this exception will throw.
Read Sun / Oracle's "To Do" list about "Reifying Generic Type Parameters." Also, most importantly, this concept has a very real name that you should read about all the time in Java - and it is called "Run Time Type Erasure" The solution posted before this Stack Overflow Answer says to use try-catch (ClassCastException) blocks, which is, actually, a valid answer.
ALSO: The answer about creating this type of TypedPredicate<T> extends Predicate<T> is not the correct answer if you intend to use your TypedPredicate<T> in any way that expects to allow Java Lambda Syntax to work with it. When you add the following method:
public interface TypedPredicate extends Predicate { Class
getTestType(); }
You will not be able to use the syntax #FunctionalInterface - which is one of the primary benefits of the class java.util.function.Predicate<T> Furthermore, there is a more severe problem in that, the Type of T is not accessible to the programmer and is not known at RunTime by the JRE
You see this part right here (since the answer has a green check mark):
{ Class<T> getTestType(); }
// Can you answer what you would write inside the method body of this
// 'extra-method' that you have added to Predicate<T> ???
The following implementation of a class that extends "Predicate" cannot be instantiated without a constructor. It cannot be called a "#FunctionalInterface" and lambda-expression cannot be used to create them:
// #FunctionalInterface (Commented Out)
public class TypedPredicate<A> implements Predicate<A>
{
public boolean test(A a) { return pred.test(a); }
// This is how the "Class of A" becomes accessible. It this
// version it is a public (and final) field.
public final Class<A> className;
// NOTE: This is the most important part here, the class of
// Variable-Type Parameter 'A' must be passed as a parameter
// to the constructor. The programmer *LITERALLY* has to tell
// the code what type 'A' actually is! This is the *BANE* of
// what I call the Java-Erasure-Fiasco programming.
public TypedPredicate(Predicate<A> pred, Class<A> className)
{
this.pred = pred;
this.className = className;
}
// Again, because a constructor is necessary, this cannot be
// called a "Functional Interface" and it will not work very
// much like a java.util.function.Predicate<T>, but it will
// indeed implement the interface.
}
The best solution would realign whatever logic you have such that you do not need to guess what type a Predicate is! The next best thing would be to try the catch (ClassCastException) version that was suggested in the previous answer.
FINALLY: This idea regarding the java.lang.Class.isAssignableFrom(...) has the right idea behind it - but only if you actually have the Class<T> clazz as an instance in front of you, so to speak. The only way to get an instance of Class<T> would be to pass it to a constructor as in the example I have posted.

How to use class name as type for method argument

I have recently run into a bit of trouble while trying to make one of my bukkit plugins version independent using reflection.
The thing is, I know how to make an instance of a class by using it's name, but I don't know how to make use of the class name as a type for a method or constructor parameter. In other words, I want to transform this:
public class Foo{
private Goat goat;
public Foo(Goat goat){
this.goat=goat;
}
Into something like this:
public class Foo{
private Class.forName("mypackage.Goat") goat;
public Foo(Class.forName("mypackage.Goat") goat){
this.goat=goat;
}
Honestly I don't know if it's even possible, but it would help a lot in making my development faster.
EDIT:
My situation is a bit more complicated than the one I presented before. That's the reason I can't actually use generics. The 'Goat' type I illustrated above is actually a class inside a package unknown to me, so I only know the class name. Therefore, I have to make use of the Class.forName method along with a small algorithm that detects the current bukkit version and appends it to the package name I already know, so net.minecraft.server would become net.minecraft.server.v1_8_R1
In other words, I only know the class name at runtime. I know, I suck at explaining...
Updated Answer:
You've clarified in the comments that you only know the type name at runtime.
The type of the field (and constructor parameter) goat is set at compile time. The only way to use runtime information to create a Foo class is to do exactly that: Generate it at runtime. There's no mechanism for declaring a placeholder that will get filled in by a string later.
If you absolutely need to do that, some prior art you could call on would be Tomcat (which compiles JSPs on-the-fly) and Vert.x (which generates classes on-the-fly). It's going to be non-trivial (unless you're just shelling out to javac, of course).
Original Answer:
You can do this with generics:
public class Foo<T> {
private T goat;
public Foo(T goat){
this.goat=goat;
}
}
Usage:
Foo<Goat> f = new Foo<>(); // Or new Foo<Goat>() (earlier Java versions didn't support the <> form)
Now, f expects goat to be a Goat.
It's just like when you're using something from the collections framework:
List<String> strings = new List<String>();
List<Date> dates = new List<Date>();
// ...

Java 8 interface/class loader changes?

I have found some difficult cautious between Java 1.7_51 and Java 1.8_20.
The initial situation:
One Interface:
interface InterfaceA {
public void doSomething();
}
Two classes:
public class ClassA implements InterfaceA {
public void doSomething() {
System.out.println("Hello World!");
}
}
public class ClassB {
public static void main(String[] args) {
ClassA a = new ClassA();
a.doSomething();
}
}
Next i have compiled the classes with (Java 1.8) -> javac *.java
after the compiler finished i removed the InterfaceA.java and InterfaceA.class file's.
Now i try again too compile only the ClassB.java and got the error message:
ClassB.java:4: error: cannot access InterfaceA
a.doSomething();
class file for InterfaceA not found
1 error
The same i have tried with java 1.7.. -> javac *.java
after the compiler finished i removed the InterfaceA.java and InterfaceA.class file's.
But know i got no error message ..
Can someone explain me this?
.. sorry for my bad english ..
The formal specification describes the process of finding the target method of an invocation expression as first searching all applicable methods and then selecting the most specific one, succeeding if there is no ambiguity.
Compare JLS 15.12.2.1. Identify Potentially Applicable Methods
The class or interface determined by compile-time step 1 (§15.12.1) is searched for all member methods that are potentially applicable to this method invocation; members inherited from superclasses and superinterfaces are included in this search.
In your case it is possible to deduce that the method found in ClassA is an exact match for which the compiler can’t find a more specific method in InterfaceA, however, the specification does not mandate that the compiler has to stop at this point, short-circuiting the search. That’s an optimization a compiler might have, but implementing the search just like formally specified, i.e. searching the entire type hierarchy first and choosing then, is appropriate.
Given how subtle and complex the process is with all the new Java 8 features and type inference, it is understandable that the current implementation is more conservative rather that optimized.
I can think of two possible explanations:
Maybe the addition of default methods, or type annotations, or something else to Java 8 meant that the compiler needed to be changed to load the classfiles for indirectly referenced interfaces.
Maybe it was just an harmless side-effect of some other restructuring of the compiler.
Either way, it doesn't necessarily make any difference to what happens at runtime. And the "fix" at compile time is to not remove the interface classfile like that.

Why the constant use of #Override in android programming? [duplicate]

In java or Android there are #Override annotations. What does it mean? I found that it is used when method is from subclass or inherited interface's method, I want to know further and other is #SuppressWarnings its also Anonation, if yes how many annonation used by java and for which purpose.
This question is also answered here, and quite succinctly:
Android #Override usage
It's an annotation that you can use to tell the compiler and your IDE that you intend the method that has that annotation to be an override of a super class method. They have warning/errors in case you make mistakes, for example if you intend to override a method but misspell it, if the annotation is there the IDE or the compiler will tell you that it is not in fact overriding the super class method and thus you can determine why and correct the misspelling.
This is all the more important for Android applications and activities for example, where all of the calls will be based on the activity lifecycle - and if you do not properly override the lifecycle methods they will never get called by the framework. Everything will compile fine, but your app will not work the way you intend it to. If you add the annotation, you'll get an error.
In other words, if you add #Override this helps you make sure you are really overriding an existing method! Pretty darn useful.
Overriding means that you are changing the behavior of a method inherited from a parent class, without changing the signature. The #Override annotation is used to mark this. It is strongly linked with the concept of polymorphism. Example:
public class A {
public void foo() {
System.out.println("A");
}
}
public class B extends A {
#Override
public void foo() { // I want to change the way foo behaves
System.out.println("B"); // I want to print B instead of A
}
}
public static void main(String[] args) {
A a = new A();
a.foo(); // prints A
A b = new B(); // I can use type B because it extends A
b.foo(); // I have overriden foo so it prints B now
}
Just to ensure that you are actually overriding it at compile time, and to improve readability
Example:
class Animal{
public void eat(Food food){
}
}
class Person extends Animal {
#Override
public void eat(String food){
}
}
This will give you compile time error since you are not actually overriding it (see the type of food)
#override its an annotation i.e meta data introduce in jdk 1.6 . If you don't write it before override method , it won't make any difference but it just use to increase the readability of compiler.
To mark that you really implement or change a method. Like meantined it's checked at compile time. That is you for instance you get an error if you want to implement #Override public void equals(final Car pObject); instead of #Override public void equals(final Object pObject);.
Just go the source for the definition of both annotations, besides other additional details: the #Override and the #SuppressWarnings from the Java specs.
It sounds like your question is more about annotations in general, so I'll answer that. Annotations provide extra meta data about the item that is being annotated. This allows other code to use that information to decide how to run. More detailed description. There are a large number build into the language, but you can write your own.
The two examples you gave tell the compiler extra information about the code it is compiling. When it sees #Override, it checks to ensure that the method is actually overriding a method. When it sees #SuppressWarnings, it know that it should ignore any compiler warnings, of the given type, that exist inside the block of code.
They can be used outside of compilers as well. There are a number of libraries that have you annotate a class object and it uses that meta data to build a database or parse an xml file.

Difference between Reflection and Late Binding in java with real time examples

While studying Java tutorials, Reflection and Late Binding have confused me. In some tutorials, they have written that they are both the same, and that there isn't any difference between Reflection and Late Binding. But other tutorials say that there is a difference.
I am confused, so can someone please explain what Reflection and Late Binding are in Java, and if posible, please give me some real world examples of both.
Thanks..
Java uses late-binding to support polymorphism; which means the decision of which of the many methods should be used is deferred until runtime.
Take the case of N classes implementing an abstract method of an interface (or an abstract class, fwiw).
public interface IMyInterface {
public void doSomething();
}
public class MyClassA implements IMyInterface {
public void doSomething(){ ... }
}
public class MyClassB implements IMyInterface {
public void doSomething(){ ... }
}
public class Caller {
public void doCall(IMyInterface i){
// which implementation of doSomething is called?
// it depends on the type of i: this is late binding
i.doSomething();
}
}
Reflection is used instead to describe code which is able to inspect other code, ie. to know which methods or attributes are available in a class, to call a method (or load a class) by name, and doing a lot of very interesting things at runtime.
A very nice explaination of reflection is here: What is reflection and why is it useful?
Late binding (also known as dynamic dispatch) does not need reflection -- it still needs to know which member to dynamically bind to at compile-time (i.e. the signature of the member is known at compile-time), even though the binding to overridden members happens at run-time.
When doing reflection, you don't even know which member you're using (not even the name is known at compile-time, let alone the signature) -- everything happens at run-time, so it's a lot slower.
Real world examples:
If you build your project with jdesktop 0.8, but ship with jdesktop 0.9, your code will still use the 0.9 features, because it takes advantage of late binding, i.e. the code that your code calls is the version that is loaded by the class loader, irrespective of the version that it was compiled against. (This is as opposed to linkers, which embed the compile-time version of the called code into the application.)
For reflection, let's say you are trying to target Java 1.5 and 1.6, but want to use tab components in 1.6 if they are available, then you'll check for their presence by using reflection on the JTabbedPane class to find the setTabComponentAt method. In this case you're building against Java 1.5, which doesn't have those features at all, so you can't call them directly or the compile will fail. However if on the end-user's system you find yourself running against 1.6 (late binding comes into play here) you can use reflection to call methods that didn't exist in 1.5.
They are related; many uses of reflection rely on late binding to be useful, but they are fundamentally different aspects of the language and its implementation.
One important issue which is addressed by "Late Binding" is the polymorphism, i.e. that the call of the proper overriden method along your class hierachy is determined during the run-time, not during compilation. Reflection is the feature to gather and manipulate information about your objects during run-time. E.g. you can get all attributes or method names of an object using its 'Class' attribute during the runtime and call those methods or manipulate its attributes.
In following code you can dynamically create a new object by the means of reflection (see how the constructor is retrieved and accessed using a Class, instead of using simply something like object obj = new MyClass( "MyInstance" ) ). In a similar way it is possible to access other constructor forms, methods and attributes. For more information about reflection in java visit: http://java.sun.com/developer/technicalArticles/ALT/Reflection/
... in some method of some class ...
Class c = getClass();
Constructor ctor = c.getConstructor( String.class );
Object obj = ctor.newInstance( "MyInstance" );
I have to disagree with most of the responses here -
Everyone calls what Java does in terms of zeroing in on a method implementation at runtime as late binding, but in my opinion its not correct to use the term late binding for what java does.
Late binding implies absolutely no checks on a method call at compile time and no compilation errors if the method does not exist.
Java however will throw a compile error if the method does not exist somewhere in the type hierarchy of the type qualifying the method call (being somewhat approximate when describing the behavior here). This is not pure traditional late binding.
What Java does in a normal non private non final non static method call would be better termed as dynamic dispatch.
However if we use reflection in Java, then Java does perform pure late binding as the compiler simply cannot verify if the called method exists or not.
Here is an example:
class A
{
public void foo()
{
System.out.println("Foo from A");
}
}
class B extends A
{
public void foo()
{
System.out.println("Foo from B");
}
}
public class C
{
public static void main(String [] args)
{
A a=new A();
B b=new B();
A ref=null;
Class ref1 = null;
ref1 = b.getClass();
ref.foo1();//will not compile because Java in this normal method
//call does some compile time checks for method and method
//signature existence. NOT late binding in its pure form.
try {
ref1.getMethod("foo1").invoke(null); //will throw a
//NoSuchMethodException at runtime, but compiles perfectly even
//though foo1 does not exist. This is pure late binding.
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

Categories

Resources