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

Invalid clone result for List.of() and Set.of() objects on JDK15 #103

Open
shm-dmitry opened this issue Dec 2, 2020 · 2 comments
Open

Comments

@shm-dmitry
Copy link

In JDK15 changed default implementation for List.of() and Set.of() methods.
So, cloner returned invalid result.

Steps to reproduce
Execute this JAVA code on JDK14 and JDK15

public class Test1 {
	private static final Cloner CLONER = Cloner.standard();

	@Test
	public void testList() {
		Assert.assertEquals(0, CLONER.deepClone(List.of()).size());
		Assert.assertEquals(1, CLONER.deepClone(List.of(1)).size());
		Assert.assertEquals(2, CLONER.deepClone(List.of(1, 2)).size());
		Assert.assertEquals(3, CLONER.deepClone(List.of(1, 2, 3)).size());
	}

	@Test
	public void testSet() {
		Assert.assertEquals(0, CLONER.deepClone(Set.of()).size());
		Assert.assertEquals(1, CLONER.deepClone(Set.of(1)).size());
		Assert.assertEquals(2, CLONER.deepClone(Set.of(1, 2)).size());
		Assert.assertEquals(3, CLONER.deepClone(Set.of(1, 2, 3)).size());
	}
}

In JDK

    private static final Object EMPTY;

    static <E> List<E> of(E e1) {
        return new ImmutableCollections.List12<>(e1);
    }

....

        List12(E e0) {
            this.e0 = Objects.requireNonNull(e0);
            // Use EMPTY as a sentinel for an unused element: not using null
            // enable constant folding optimizations over single-element lists
            this.e1 = EMPTY;
        }

...

        public int size() {
            return e1 != EMPTY ? 2 : 1;
        }

Problem in internal EMPTY value - library cloned it in e1 field.

@shm-dmitry
Copy link
Author

shm-dmitry commented Dec 2, 2020

Workaround:

	private static final Cloner CLONER = Cloner.standard();

	static {
		try {
			var list = List.of(1);

			var field = list.getClass().getDeclaredField("e1");
			field.setAccessible(true);
			var value = field.get(list);

			if (value != null) {
				CLONER.registerConstant(value);
			}
		} catch (Exception e) {
			// ignore
		}
	}

@tweimer
Copy link
Contributor

tweimer commented Jan 3, 2021

I can confirm. It should rather be fixed by adding a custom IFastCloner, like in FastClonerArrayList.
In Cloner.registerFastCloners(), you can register those custom cloner.

kostaskougios added a commit that referenced this issue Aug 4, 2021
fix the issue #103 by create two new FastCloners
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants