Skip to content

java.lang.ClassCastException in very specific case on compiled ObjIntMap<String>.keySet().retainAll(...) #66

Open
@jmassenet

Description

Please see the attached file for a test reproducing the behavior:
objIntMapRetainAll.zip

This problem happens when using Koloboke compile to implement a ObjIntMap<String> map, and then trying to remove elements using keySet().retainAll(...).

This issue seems to happen when the first element of the backing array needs to be removed.

In the generated source code, this block adds a tombstone element:

if (indexToShift > indexToRemove) {
    firstDelayedRemoved = i;
    keys[indexToRemove] = XXX.Support.ObjHash.REMOVED;
    break closeDeletion;
} 

But then, the check on key existence for each iteration of the loop is:

if ((key = ((String) (keys[i]))) != null) {
    ...
}

So when the check is executed against the REMOVED object, it fails with this exception:

java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String
	at koloboke.KolobokeObjIntMapRetainAllTest_StringKeyObjIntMap.retainAll(KolobokeObjIntMapRetainAllTest_StringKeyObjIntMap.java:2120)
	at koloboke.KolobokeObjIntMapRetainAllTest_StringKeyObjIntMap$KeyView.retainAll(KolobokeObjIntMapRetainAllTest_StringKeyObjIntMap.java:353)
	at koloboke.ObjIntMapRetainAllTest.performTest(ObjIntMapRetainAllTest.java:35)
	at koloboke.ObjIntMapRetainAllTest.testWithStringKey(ObjIntMapRetainAllTest.java:16)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
	at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
	at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
	at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
	at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
	at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
	at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)

The workaround, as demonstrated by the attached project, it just to use a generic ObjIntMap instead.

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions