Originally reported as https://github.com/cloudbees/groovy-cps/issues/105.
Using a LinkedList in a Groovy for in loop in a Pipeline sometimes (but not always!) causes the following NotSerializableException:
Here is a simple Pipeline that can reproduce the problem (make sure you are using the MAX_SURVIVABILITY durability level):
My diagnosis of the issue can be found in this and earlier comments. When resolving this call internally, sometimes Groovy treats it as a call to List.iterator, but sometimes it treats it as a call to Deque.iterator() (presumably because LinkedList implements both interfaces and there is some nondeterministic behavior somewhere). The method that Groovy chooses changes which IteratorHack category methods are valid (the class of the selected method much match the first parameter of the category method), so adding IteratorHack.iterator(Deque) fixes the issue.
This probably also affects other types, and maybe we need to add other methods to IteratorHack as well.
I am not sure about the root cause of the nondeterminism, and I was not able to reproduce it using a standalone Groovy script. See this comment for addition details. Notably, running a JenkinsRule-based reproduction test in a loop inside of an @Test method showed that the test either always fails or always passes in the same JVM instance, so maybe the nondeterminism is caused by something like ordering of methods in Java's reflection APIs, which I think is undefined but consistent during the lifetime of a single JVM instance.