Welcome! Please see the About page for a little more info on how this works.

+2 votes
in Records and Types by

Compiling a deftype that implements List on Java 21 will create a class that includes a reference to the (new to Java 21) SequencedCollection type (which introduces a new method reverse). Loading the compiled class will throw in an older Java runtime as the SequencedCollection type doesn't exist.

Given repro.clj:

(ns repro)

(deftype C []

Compiling with Java 21 JDK to a class, javap shows:

public final class repro.C implements java.util.List,clojure.lang.IType {
  public repro.C();
       0: aload_0
       1: invokespecial #13  // Method java/lang/Object."<init>":()V
       4: return

  public static clojure.lang.IPersistentVector getBasis();
       0: invokestatic  #20  // Method clojure/lang/Tuple.create:()Lclojure/lang/IPersistentVector;
       3: areturn

  public java.util.SequencedCollection reversed();
       0: aload_0
       1: invokeinterface #25,  1   // InterfaceMethod java/util/List.reversed:()Ljava/util/List;
       6: areturn

  public static {};
       0: return

Loading this class in Clojure with an older Java version throws:

user=> (require 'repro)
Execution error (ClassNotFoundException) at jdk.internal.loader.BuiltinClassLoader/loadClass (BuiltinClassLoader.java:641).

List includes a default reversed() method implementation for the SequenceCollection parent interface. Not sure why this forwarding method is getting created here but it's presumably different than others because it's a parent default method impl that we're forwarding to.

1 Answer

+1 vote

Logged as https://clojure.atlassian.net/browse/CLJ-2838 and I put a bit more analysis on the bottom of that.