PR 23 is not right. PR 25 solves the issue for new installations, including in functional tests, but does not yet address compatibility.
From actually looking at the stack trace, there is more going on than was initially suspected.
First of all, even without any patch, the problem is not reproducible for jobs newly configured with current versions of the plugin, even if you start with a pre-2.102 version of Jenkins! That is because the @DataBoundConstructor, which is used whenever you actually save from a current configuration form, does not directly use the getDefaultShortcutList() method, which is the problematic one since that is the only production code to call the problematic ResultShortcut overload taking Result.... (There is some test code which calls this, which is why functional tests can reproduce a stack trace, but these are not exercising a realistic code path.) The method is called from MatrixCombinationsParameterDefinition/config.jelly, but the result is then “flattened” into an HTML form, which upon submission calls the usual List<String> resultsToCheck constructor and there is no problem.
The problem, AFAICT, comes from older settings (pre-1.1.0, according to code comments) where MatrixCombinationsParameterDefinition.readResolve is called which in turns calls a MatrixCombinationsParameterDefinition overload that calls getDefaultShortcutList(). But even that should not really be a problem: either you are just loading the old config.xml, which lacks a shortcutList field so the in-memory version gets it populated, but there is no serialization or deserialization of ResultShortcut, so there is no JEP-200 issue; or you clicked Configure and resaved the project, in which case again the configuration is flattened and the List<String> overload is used, which bypasses Lists.transform and thus any JEP-200 problems. In principle there could be some code which calls Job.save without going through the configuration form, and that could crash, but this is unusual.
So back to that stack trace. If you look at the sequence of fields being written, and the top-level object, you will see that the problem is not in saving the job configuration at all! It is in saving a build. But this makes no sense—a ParameterDefinition is part of job-level configuration. All that the build needs to store is ParameterValue instances. The stack trace starts to make sense when you look at a build.xml record saved by an old version of Jenkins:
<combinations class="java.util.Collections$UnmodifiableRandomAccessList" resolves-to="java.util.Collections$UnmodifiableList">
OK, the use of unmodifiable lists in the XStream form is gratuitous, but nothing here really harmful. And then by a new version of Jenkins:
<resultsToCheck class="java.util.Collections$UnmodifiableRandomAccessList" resolves-to="java.util.Collections$UnmodifiableList">
So this is copying the whole <parameterDefinitions> section from the job’s config.xml. So now if we are loading an old config.xml, which contains no problematic types, and populating some of the deeply nested fields (resultsToCheck) in memory with problematic types even though we do not save them back to config.xml, when we go to do a build those types do get saved to build.xml and everything explodes.
And this is all due to a core bug, evidently introduced by SECURITY-170. Until now, no one bothered to look at a parameterized build.xml, I guess, because if you do the problem is pretty obvious.