JDK-8350925 : Issues with the Lambda-Notation of the form variable::method
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.io:serialization
  • Affected Version: 8,11,17,22,23,24,25
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2025-02-28
  • Updated: 2025-03-03
Related Reports
Relates :  
Description
A DESCRIPTION OF THE PROBLEM :
I have a system that heavily depends on the serialization of Lamdas. I regularly had issues with the Lambda-Notation of the form variable::method, but () -> variable.method() worked find. So I had a workaround :-) Now I have analyzed the reason for this and found https://bugs.openjdk.org/browse/JDK-8154236. This is exactly my case. Its an old and best known case: Please fix it. Thank you very much!


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
https://bugs.openjdk.org/browse/JDK-8154236.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Should not cause an exception during DeSerialization
ACTUAL -
Exception in Deserializing

---------- BEGIN SOURCE ----------
public class SerializationProblem {

	@FunctionalInterface
	public interface MyFunctionalInterface extends Serializable {
		int doApply();
	}

	static class MySuperclass implements Serializable {
		public int returnValue() {
			return 1;
		}
	}

	static class MyImplementation extends MySuperclass {
	}

	static class MyOtherImplementation extends MySuperclass {
	}

	static class SuccessfullDeserializable implements Serializable {
		private final MyFunctionalInterface myFunctionalInterface;
		private final MyFunctionalInterface myOtherFunctionalInterface;

		SuccessfullDeserializable() {
			final MyImplementation myImplementation = new MyImplementation();
			this.myFunctionalInterface = myImplementation::returnValue;
			final MyImplementation myOtherImplementation = new MyImplementation();
			this.myOtherFunctionalInterface = myOtherImplementation::returnValue;
		}
	}

	static class FailingDeserializable implements Serializable {
		private final MyFunctionalInterface myFunctionalInterface;
		private final MyFunctionalInterface myOtherFunctionalInterface;

		FailingDeserializable() {
			final MyImplementation myImplementation = new MyImplementation();
			this.myFunctionalInterface = myImplementation::returnValue;
			final MyOtherImplementation myOtherImplementation = new MyOtherImplementation();
			this.myOtherFunctionalInterface = myOtherImplementation::returnValue;
		}
	}

	private static Object serializeAndDeserialize(final Serializable serializable) throws IOException, ClassNotFoundException {
		final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		final ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
		objectOutputStream.writeObject(serializable);
		objectOutputStream.flush();
		final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
		final ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
		return objectInputStream.readObject();
	}

	public static void main(final String[] args) throws Exception {
		final Object first = serializeAndDeserialize(new SuccessfullDeserializable() {});
		System.out.println(first.getClass().getName() + " successfully deserialized");

		final Object second = serializeAndDeserialize(new FailingDeserializable() {});
		// not reached....
		System.out.println(second.getClass().getName() + " successfully deserialized");
	}
}

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