Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Private nested record cannot be serialized #873

Closed
robertvazan opened this issue Dec 29, 2021 · 6 comments · Fixed by #875
Closed

Private nested record cannot be serialized #873

robertvazan opened this issue Dec 29, 2021 · 6 comments · Fixed by #875
Labels

Comments

@robertvazan
Copy link

Describe the bug
I am getting this exception:

com.esotericsoftware.kryo.KryoException: java.lang.IllegalAccessException: class com.esotericsoftware.kryo.serializers.RecordSerializer cannot access a member of class mypkg.A$B with modifiers "public"
	at com.esotericsoftware.kryo.serializers.RecordSerializer.componentValue(RecordSerializer.java:208)
	at com.esotericsoftware.kryo.serializers.RecordSerializer.write(RecordSerializer.java:92)
	at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:642)
	at com.esotericsoftware.kryo.serializers.ReflectField.write(ReflectField.java:70)
	at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:108)
	at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:642)
	at com.esotericsoftware.kryo.serializers.ReflectField.write(ReflectField.java:70)
	at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:108)
	at com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:711)
	...
Caused by: java.lang.IllegalAccessException: class com.esotericsoftware.kryo.serializers.RecordSerializer cannot access a member of class mypkg.A$B with modifiers "public"
	at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:392)
	at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:674)
	at java.base/java.lang.reflect.Method.invoke(Method.java:560)
	at com.esotericsoftware.kryo.serializers.RecordSerializer.componentValue(RecordSerializer.java:206)
	... 19 more

To Reproduce

public class A {
    private static record B(String y) {}
    private B x;
}

// serialized with:
kryo.writeClassAndObject(output, someA);

Environment:

  • OS: Linux
  • JDK Version: 17
  • Kryo Version: 5.2.1

Additional context
There's no exception when the record is public.

@theigl
Copy link
Collaborator

theigl commented Dec 29, 2021

@robertvazan:

I tried to reproduce it with this test in RecordSerializerTest:

	@Test
	void testNestedNonPublicRecords () {
		kryo.register(ClassWithNestedRecord.class);
		kryo.register(ClassWithNestedRecord.B.class);

		roundTrip(4, new ClassWithNestedRecord(new ClassWithNestedRecord.B("s")));
	}

	static class ClassWithNestedRecord {
		private record B(String y) { }
		private B x;

		public ClassWithNestedRecord () {}

		public ClassWithNestedRecord (B s) {
			x = s;
		}

		public boolean equals (Object o) {
			if (this == o) return true;
			if (o == null || getClass() != o.getClass()) return false;
			ClassWithNestedRecord a = (ClassWithNestedRecord)o;
			return Objects.equals(x, a.x);
		}
	}

This test passes.

Please share a runnable test that fails.

@robertvazan
Copy link
Author

This test fails:

public class KryoRecordTest {
	static class A {
		private record B(String y) {
		}
		private B x;
		public A() {
			x = new B("w");
		}
	}
	@Test
	void test() throws IOException {
		try (	var stream = new ByteArrayOutputStream();
			var output = new Output(stream)) {
			ThreadLocalKryo.get().writeClassAndObject(output, new A());
		}
	}
}

Exception:

com.esotericsoftware.kryo.KryoException: 
java.lang.IllegalAccessException: class com.esotericsoftware.kryo.serializers.RecordSerializer cannot access a member of class mypkg.KryoRecordTest$A$B with modifiers "public"
Serialization trace:
Could not retrieve record components (mypkg.KryoRecordTest$A$B)
y (java.lang.String)
x (mypkg.KryoRecordTest$A)
	at mypkg.KryoRecordTest.test(KryoRecordTest.java:21)
Caused by: java.lang.IllegalAccessException: class com.esotericsoftware.kryo.serializers.RecordSerializer cannot access a member of class mypkg.KryoRecordTest$A$B with modifiers "public"
	at mypkg.KryoRecordTest.test(KryoRecordTest.java:21)

From pom.xml:

	<properties>
		<maven.compiler.release>17</maven.compiler.release>
		...
	</properties>

	<dependencies>
		<dependency>
			<groupId>com.esotericsoftware</groupId>
			<artifactId>kryo</artifactId>
			<version>5.2.1</version>
		</dependency>
		...
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<compilerArgs>
						<compilerArg>-parameters</compilerArg>
						<compilerArg>--enable-preview</compilerArg>
					</compilerArgs>
				</configuration>
			</plugin>
			<plugin>
				<artifactId>maven-surefire-plugin</artifactId>
				<version>3.0.0-M5</version>
				<configuration>
					<argLine>--enable-preview</argLine>
				</configuration>
			</plugin>
		</plugins>
	</build>

There is currently no moduie-info.java in the project, i.e. it's an unnamed module.

@theigl
Copy link
Collaborator

theigl commented Dec 30, 2021

There is currently no moduie-info.java in the project, i.e. it's an unnamed module.

I was able to reproduce this issue by moving the test record to a different package. #875 should solve this problem.

@theigl
Copy link
Collaborator

theigl commented Dec 30, 2021

Please confirm the fix against the latest SNAPSHOT build.

@robertvazan
Copy link
Author

The fix works. Thank you.

@theigl
Copy link
Collaborator

theigl commented Jan 3, 2022

@robertvazan: Thanks a lot! Please let me know if you run into any other issue with record.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging a pull request may close this issue.

2 participants