wip
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmClassVisitor.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmClassVisitor.java
index 884d04b..723e52b 100644
--- a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmClassVisitor.java
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmClassVisitor.java
@@ -87,6 +87,7 @@
     var field = new Field();
     field.name = name;
     field.type = TypeUtils.typeUsage(Type.getType(descriptor));
+    field.descriptor = descriptor;
     field.defaultValue = value;
     field.modifiers = TypeUtils.access(access);
     if ((access & ACC_ENUM) != 0) {
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Field.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Field.java
index ced5cea..0afd9b0 100644
--- a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Field.java
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Field.java
@@ -14,6 +14,7 @@
   public String name;
   public TypeUsage type;
   public Object defaultValue;
+  public String descriptor;
 
   public JavaDocComment javadoc;
   public List<JavaAnnotation> annotations = new ArrayList<>();
diff --git a/pkgs/jnigen/jnigen_symbols.json b/pkgs/jnigen/jnigen_symbols.json
new file mode 100644
index 0000000..00a1f6c
--- /dev/null
+++ b/pkgs/jnigen/jnigen_symbols.json
@@ -0,0 +1,8753 @@
+{
+  "formatVersion": "1.0.0",
+  "packageName": "tbd",
+  "files": {
+    "test/simple_package_test/bindings/simple_package.dart": {
+      "classes": {
+        "com.github.dart_lang.jnigen.simple_package.Example$Nested$NestedTwice": {
+          "name": "Example$Nested$NestedTwice",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "ZERO": {
+              "name": "ZERO",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            }
+          },
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "<clinit>()V": {
+              "name": "$_clinit_",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.simple_package.Example$Nested": {
+          "name": "Example$Nested",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "value": {
+              "name": "value",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "boolean"
+                }
+              }
+            }
+          },
+          "methods": {
+            "<init>(Z)V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "usesAnonymousInnerClass()V": {
+              "name": "usesAnonymousInnerClass",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "getValue()Z": {
+              "name": "getValue",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "boolean"
+                }
+              }
+            },
+            "setValue(Z)V": {
+              "name": "setValue",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.simple_package.Example$NonStaticNested": {
+          "name": "Example$NonStaticNested",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "ok": {
+              "name": "ok",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "boolean"
+                }
+              }
+            }
+          },
+          "methods": {
+            "<init>(Lcom/github/dart_lang/jnigen/simple_package/Example;)V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "$$outerClass",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "com.github.dart_lang.jnigen.simple_package.Example",
+                      "typeArguments": [],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.simple_package.Example": {
+          "name": "Example",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "ON": {
+              "name": "ON",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            },
+            "OFF": {
+              "name": "OFF",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            },
+            "PI": {
+              "name": "PI",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "double"
+                }
+              }
+            },
+            "SEMICOLON": {
+              "name": "SEMICOLON",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "char"
+                }
+              }
+            },
+            "SEMICOLON_STRING": {
+              "name": "SEMICOLON_STRING",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "unusedRandom": {
+              "name": "unusedRandom",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.Random",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "amount": {
+              "name": "amount",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            },
+            "pi": {
+              "name": "pi",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "double"
+                }
+              }
+            },
+            "asterisk": {
+              "name": "asterisk",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "char"
+                }
+              }
+            },
+            "name": {
+              "name": "name",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "nested": {
+              "name": "nested",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.simple_package.Example$Nested",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "number": {
+              "name": "number",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            },
+            "isUp": {
+              "name": "isUp",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "boolean"
+                }
+              }
+            },
+            "codename": {
+              "name": "codename",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "random": {
+              "name": "random",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.Random",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "protectedField": {
+              "name": "protectedField",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.Random",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "methods": {
+            "getAmount()I": {
+              "name": "getAmount",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            },
+            "getPi()D": {
+              "name": "getPi",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "double"
+                }
+              }
+            },
+            "getAsterisk()C": {
+              "name": "getAsterisk",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "char"
+                }
+              }
+            },
+            "getName()Ljava/lang/String;": {
+              "name": "getName",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "getNestedInstance()Lcom/github/dart_lang/jnigen/simple_package/Example$Nested;": {
+              "name": "getNestedInstance",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.simple_package.Example$Nested",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "setAmount(I)V": {
+              "name": "setAmount",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "i",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "setName(Ljava/lang/String;)V": {
+              "name": "setName",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "setNestedInstance(Lcom/github/dart_lang/jnigen/simple_package/Example$Nested;)V": {
+              "name": "setNestedInstance",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "nested",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "com.github.dart_lang.jnigen.simple_package.Example$Nested",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "max4(IIII)I": {
+              "name": "max4",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "i",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i1",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i2",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i3",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            },
+            "max8(IIIIIIII)I": {
+              "name": "max8",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "i",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i1",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i2",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i3",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i4",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i5",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i6",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i7",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            },
+            "getNumber()I": {
+              "name": "getNumber",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            },
+            "setNumber(I)V": {
+              "name": "setNumber",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "i",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "getIsUp()Z": {
+              "name": "getIsUp",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "boolean"
+                }
+              }
+            },
+            "setUp(Z)V": {
+              "name": "setUp",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "getCodename()Ljava/lang/String;": {
+              "name": "getCodename",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "setCodename(Ljava/lang/String;)V": {
+              "name": "setCodename",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "getRandom()Ljava/util/Random;": {
+              "name": "getRandom",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.Random",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "setRandom(Ljava/util/Random;)V": {
+              "name": "setRandom",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "random",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.Random",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "getRandomLong()J": {
+              "name": "getRandomLong",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "long"
+                }
+              }
+            },
+            "add4Longs(JJJJ)J": {
+              "name": "add4Longs",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "j",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "long"
+                    }
+                  }
+                },
+                {
+                  "name": "j1",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "long"
+                    }
+                  }
+                },
+                {
+                  "name": "j2",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "long"
+                    }
+                  }
+                },
+                {
+                  "name": "j3",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "long"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "long"
+                }
+              }
+            },
+            "add8Longs(JJJJJJJJ)J": {
+              "name": "add8Longs",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "j",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "long"
+                    }
+                  }
+                },
+                {
+                  "name": "j1",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "long"
+                    }
+                  }
+                },
+                {
+                  "name": "j2",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "long"
+                    }
+                  }
+                },
+                {
+                  "name": "j3",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "long"
+                    }
+                  }
+                },
+                {
+                  "name": "j4",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "long"
+                    }
+                  }
+                },
+                {
+                  "name": "j5",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "long"
+                    }
+                  }
+                },
+                {
+                  "name": "j6",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "long"
+                    }
+                  }
+                },
+                {
+                  "name": "j7",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "long"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "long"
+                }
+              }
+            },
+            "getRandomNumericString(Ljava/util/Random;)Ljava/lang/String;": {
+              "name": "getRandomNumericString",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "random",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.Random",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "privateMethod(Ljava/lang/String;Ljava/lang/String;)V": {
+              "name": "privateMethod",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "string1",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "protectedMethod(Ljava/lang/String;Ljava/lang/String;)V": {
+              "name": "protectedMethod",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "string1",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "finalMethod()V": {
+              "name": "finalMethod",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "getList()Ljava/util/List;": {
+              "name": "getList",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.List",
+                  "typeArguments": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.String",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "joinStrings(Ljava/util/List;Ljava/lang/String;)Ljava/lang/String;": {
+              "name": "joinStrings",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "list",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.List",
+                      "typeArguments": [
+                        {
+                          "kind": "declared",
+                          "type": {
+                            "binaryName": "java.lang.String",
+                            "typeArguments": [],
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "methodWithSeveralParams(CLjava/lang/String;[ILjava/lang/CharSequence;Ljava/util/List;Ljava/util/Map;)V": {
+              "name": "methodWithSeveralParams",
+              "typeParameters": [
+                {
+                  "name": "T",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.CharSequence",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "c",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "char"
+                    }
+                  }
+                },
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "is$",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "elementType": {
+                        "kind": "primitive",
+                        "type": {
+                          "name": "int"
+                        }
+                      },
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "charSequence",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "T",
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "list",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.List",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "map",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.Map",
+                      "typeArguments": [
+                        {
+                          "kind": "declared",
+                          "type": {
+                            "binaryName": "java.lang.String",
+                            "typeArguments": [],
+                            "nullability": "platform"
+                          }
+                        },
+                        {
+                          "kind": "wildcard",
+                          "type": {
+                            "extendsBound": {
+                              "kind": "declared",
+                              "type": {
+                                "binaryName": "java.lang.CharSequence",
+                                "typeArguments": [],
+                                "nullability": "platform"
+                              }
+                            },
+                            "superBound": null,
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "<init>(I)V": {
+              "name": "new$1",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "i",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "<init>(IZ)V": {
+              "name": "new$2",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "i",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "<init>(IZLjava/lang/String;)V": {
+              "name": "new$3",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "i",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                },
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "<init>(IIIIIIII)V": {
+              "name": "new$4",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "i",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i1",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i2",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i3",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i4",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i5",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i6",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i7",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "whichExample()I": {
+              "name": "whichExample",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            },
+            "addInts(II)I": {
+              "name": "addInts",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "i",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i1",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            },
+            "getArr()[I": {
+              "name": "getArr",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "elementType": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  },
+                  "nullability": "platform"
+                }
+              }
+            },
+            "addAll([I)I": {
+              "name": "addAll",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "is$",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "elementType": {
+                        "kind": "primitive",
+                        "type": {
+                          "name": "int"
+                        }
+                      },
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            },
+            "getSelf()Lcom/github/dart_lang/jnigen/simple_package/Example;": {
+              "name": "getSelf",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.simple_package.Example",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "throwException()V": {
+              "name": "throwException",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "overloaded()V": {
+              "name": "overloaded",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "overloaded(ILjava/lang/String;)V": {
+              "name": "overloaded$1",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "i",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "overloaded(I)V": {
+              "name": "overloaded$2",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "i",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "overloaded(Ljava/util/List;Ljava/lang/String;)V": {
+              "name": "overloaded$3",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "list",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.List",
+                      "typeArguments": [
+                        {
+                          "kind": "declared",
+                          "type": {
+                            "binaryName": "java.lang.Integer",
+                            "typeArguments": [],
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "overloaded(Ljava/util/List;)V": {
+              "name": "overloaded$4",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "list",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.List",
+                      "typeArguments": [
+                        {
+                          "kind": "declared",
+                          "type": {
+                            "binaryName": "java.lang.Integer",
+                            "typeArguments": [],
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "<clinit>()V": {
+              "name": "$_clinit_",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.simple_package.Exceptions": {
+          "name": "Exceptions",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "<init>(F)V": {
+              "name": "new$1",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "f",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "float"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "<init>(IIIIII)V": {
+              "name": "new$2",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "i",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i1",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i2",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i3",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i4",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i5",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "staticObjectMethod()Ljava/lang/Object;": {
+              "name": "staticObjectMethod",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.Object",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "staticIntMethod()I": {
+              "name": "staticIntMethod",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            },
+            "staticObjectArrayMethod()[Ljava/lang/Object;": {
+              "name": "staticObjectArrayMethod",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "elementType": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.Object",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  },
+                  "nullability": "platform"
+                }
+              }
+            },
+            "staticIntArrayMethod()[I": {
+              "name": "staticIntArrayMethod",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "elementType": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  },
+                  "nullability": "platform"
+                }
+              }
+            },
+            "objectMethod()Ljava/lang/Object;": {
+              "name": "objectMethod",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.Object",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "intMethod()I": {
+              "name": "intMethod",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            },
+            "objectArrayMethod()[Ljava/lang/Object;": {
+              "name": "objectArrayMethod",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "elementType": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.Object",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  },
+                  "nullability": "platform"
+                }
+              }
+            },
+            "intArrayMethod()[I": {
+              "name": "intArrayMethod",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "elementType": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  },
+                  "nullability": "platform"
+                }
+              }
+            },
+            "throwNullPointerException()I": {
+              "name": "throwNullPointerException",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            },
+            "throwFileNotFoundException()Ljava/io/InputStream;": {
+              "name": "throwFileNotFoundException",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.io.InputStream",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "throwClassCastException()Ljava/io/FileInputStream;": {
+              "name": "throwClassCastException",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.io.FileInputStream",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "throwArrayIndexException()I": {
+              "name": "throwArrayIndexException",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            },
+            "throwArithmeticException()I": {
+              "name": "throwArithmeticException",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            },
+            "throwLoremIpsum()V": {
+              "name": "throwLoremIpsum",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.simple_package.Fields$Nested": {
+          "name": "Fields$Nested",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "hundred": {
+              "name": "hundred",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "long"
+                }
+              }
+            },
+            "BEST_GOD": {
+              "name": "BEST_GOD",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "<clinit>()V": {
+              "name": "$_clinit_",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.simple_package.Fields": {
+          "name": "Fields",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "amount": {
+              "name": "amount",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            },
+            "pi": {
+              "name": "pi",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "double"
+                }
+              }
+            },
+            "asterisk": {
+              "name": "asterisk",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "char"
+                }
+              }
+            },
+            "name": {
+              "name": "name",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "i": {
+              "name": "i",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.Integer",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "trillion": {
+              "name": "trillion",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "long"
+                }
+              }
+            },
+            "isAchillesDead": {
+              "name": "isAchillesDead",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "boolean"
+                }
+              }
+            },
+            "bestFighterInGreece": {
+              "name": "bestFighterInGreece",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "random": {
+              "name": "random",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.Random",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "euroSymbol": {
+              "name": "euroSymbol",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "char"
+                }
+              }
+            }
+          },
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "<clinit>()V": {
+              "name": "$_clinit_",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.pkg2.C2": {
+          "name": "C2",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "CONSTANT": {
+              "name": "CONSTANT",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            }
+          },
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "<clinit>()V": {
+              "name": "$_clinit_",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.pkg2.Example": {
+          "name": "Example$1",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "whichExample()I": {
+              "name": "whichExample",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.enums.Colors$RGB": {
+          "name": "Colors$RGB",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "red": {
+              "name": "red",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            },
+            "green": {
+              "name": "green",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            },
+            "blue": {
+              "name": "blue",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            }
+          },
+          "methods": {
+            "<init>(III)V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "i",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i1",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i2",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "equals(Ljava/lang/Object;)Z": {
+              "name": "equals",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.Object",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "boolean"
+                }
+              }
+            },
+            "hashCode()I": {
+              "name": "hashCode",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.enums.Colors": {
+          "name": "Colors",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Enum",
+              "typeArguments": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "com.github.dart_lang.jnigen.enums.Colors",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "red": {
+              "name": "red",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.enums.Colors",
+                  "typeArguments": [],
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "green": {
+              "name": "green",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.enums.Colors",
+                  "typeArguments": [],
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "blue": {
+              "name": "blue",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.enums.Colors",
+                  "typeArguments": [],
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "code": {
+              "name": "code",
+              "type": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            }
+          },
+          "methods": {
+            "values()[Lcom/github/dart_lang/jnigen/enums/Colors;": {
+              "name": "values",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "elementType": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "com.github.dart_lang.jnigen.enums.Colors",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  },
+                  "nullability": "platform"
+                }
+              }
+            },
+            "valueOf(Ljava/lang/String;)Lcom/github/dart_lang/jnigen/enums/Colors;": {
+              "name": "valueOf",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.enums.Colors",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "<init>(Ljava/lang/String;II)V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "i",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "i1",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "toRGB()Lcom/github/dart_lang/jnigen/enums/Colors$RGB;": {
+              "name": "toRGB",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.enums.Colors$RGB",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "<clinit>()V": {
+              "name": "$_clinit_",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.generics.GenericTypeParams": {
+          "name": "GenericTypeParams",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "S",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.CharSequence",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            },
+            {
+              "name": "K",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "com.github.dart_lang.jnigen.generics.GenericTypeParams",
+                    "typeArguments": [
+                      {
+                        "kind": "typeVariable",
+                        "type": {
+                          "name": "S",
+                          "nullability": "platform"
+                        }
+                      },
+                      {
+                        "kind": "typeVariable",
+                        "type": {
+                          "name": "K",
+                          "nullability": "platform"
+                        }
+                      }
+                    ],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        },
+        "com.github.dart_lang.jnigen.generics.GrandParent$Parent$Child": {
+          "name": "GrandParent$Parent$Child",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "grandParentValue": {
+              "name": "grandParentValue",
+              "type": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "parentValue": {
+              "name": "parentValue",
+              "type": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "S",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "value": {
+              "name": "value",
+              "type": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "U",
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "methods": {
+            "<init>(Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent;Ljava/lang/Object;)V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "$$outerClass",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "com.github.dart_lang.jnigen.generics.GrandParent$Parent",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "platform"
+                          }
+                        },
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "S",
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                },
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "U",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "T",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            },
+            {
+              "name": "S",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            },
+            {
+              "name": "U",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        },
+        "com.github.dart_lang.jnigen.generics.GrandParent$Parent": {
+          "name": "GrandParent$Parent",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "parentValue": {
+              "name": "parentValue",
+              "type": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "value": {
+              "name": "value",
+              "type": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "S",
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "methods": {
+            "<init>(Lcom/github/dart_lang/jnigen/generics/GrandParent;Ljava/lang/Object;)V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "$$outerClass",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "com.github.dart_lang.jnigen.generics.GrandParent",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                },
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "S",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "T",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            },
+            {
+              "name": "S",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        },
+        "com.github.dart_lang.jnigen.generics.GrandParent$StaticParent$Child": {
+          "name": "GrandParent$StaticParent$Child",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "parentValue": {
+              "name": "parentValue",
+              "type": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "S",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "value": {
+              "name": "value",
+              "type": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "U",
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "methods": {
+            "<init>(Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;Ljava/lang/Object;Ljava/lang/Object;)V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "$$outerClass",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "com.github.dart_lang.jnigen.generics.GrandParent$StaticParent",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "S",
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                },
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "S",
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "object1",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "U",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "S",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            },
+            {
+              "name": "U",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        },
+        "com.github.dart_lang.jnigen.generics.GrandParent$StaticParent": {
+          "name": "GrandParent$StaticParent",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "value": {
+              "name": "value",
+              "type": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "S",
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "methods": {
+            "<init>(Ljava/lang/Object;)V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "S",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "S",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        },
+        "com.github.dart_lang.jnigen.generics.GrandParent": {
+          "name": "GrandParent",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "value": {
+              "name": "value",
+              "type": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "methods": {
+            "<init>(Ljava/lang/Object;)V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "T",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "stringParent()Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent;": {
+              "name": "stringParent",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.generics.GrandParent$Parent",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "T",
+                        "nullability": "platform"
+                      }
+                    },
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.String",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "varParent(Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent;": {
+              "name": "varParent",
+              "typeParameters": [
+                {
+                  "name": "S",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "S",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.generics.GrandParent$Parent",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "T",
+                        "nullability": "platform"
+                      }
+                    },
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "S",
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "stringStaticParent()Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;": {
+              "name": "stringStaticParent",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.generics.GrandParent$StaticParent",
+                  "typeArguments": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.String",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "varStaticParent(Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;": {
+              "name": "varStaticParent",
+              "typeParameters": [
+                {
+                  "name": "S",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "S",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.generics.GrandParent$StaticParent",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "S",
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "staticParentWithSameType()Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;": {
+              "name": "staticParentWithSameType",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.generics.GrandParent$StaticParent",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "T",
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "T",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        },
+        "com.github.dart_lang.jnigen.generics.MyMap$MyEntry": {
+          "name": "MyMap$MyEntry",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "key": {
+              "name": "key",
+              "type": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "K",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "value": {
+              "name": "value",
+              "type": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "methods": {
+            "<init>(Lcom/github/dart_lang/jnigen/generics/MyMap;Ljava/lang/Object;Ljava/lang/Object;)V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "$$outerClass",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "com.github.dart_lang.jnigen.generics.MyMap",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "K",
+                            "nullability": "platform"
+                          }
+                        },
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "V",
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                },
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "K",
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "object1",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "V",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "K",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            },
+            {
+              "name": "V",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        },
+        "com.github.dart_lang.jnigen.generics.MyMap": {
+          "name": "MyMap",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "map": {
+              "name": "map",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.Map",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "K",
+                        "nullability": "platform"
+                      }
+                    },
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "V",
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "get(Ljava/lang/Object;)Ljava/lang/Object;": {
+              "name": "get",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "K",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;": {
+              "name": "put",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "K",
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "object1",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "V",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "entryStack()Lcom/github/dart_lang/jnigen/generics/MyStack;": {
+              "name": "entryStack",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.generics.MyStack",
+                  "typeArguments": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "com.github.dart_lang.jnigen.generics.MyMap$MyEntry",
+                        "typeArguments": [
+                          {
+                            "kind": "typeVariable",
+                            "type": {
+                              "name": "K",
+                              "nullability": "platform"
+                            }
+                          },
+                          {
+                            "kind": "typeVariable",
+                            "type": {
+                              "name": "V",
+                              "nullability": "platform"
+                            }
+                          }
+                        ],
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "K",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            },
+            {
+              "name": "V",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        },
+        "com.github.dart_lang.jnigen.generics.MyStack": {
+          "name": "MyStack",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "stack": {
+              "name": "stack",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.Stack",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "T",
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "fromArray([Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/MyStack;": {
+              "name": "fromArray",
+              "typeParameters": [
+                {
+                  "name": "T",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "objects",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "elementType": {
+                        "kind": "typeVariable",
+                        "type": {
+                          "name": "T",
+                          "nullability": "platform"
+                        }
+                      },
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.generics.MyStack",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "T",
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "fromArrayOfArrayOfGrandParents([[Lcom/github/dart_lang/jnigen/generics/GrandParent;)Lcom/github/dart_lang/jnigen/generics/MyStack;": {
+              "name": "fromArrayOfArrayOfGrandParents",
+              "typeParameters": [
+                {
+                  "name": "S",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "grandParents",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "elementType": {
+                        "kind": "declared",
+                        "type": {
+                          "elementType": {
+                            "kind": "declared",
+                            "type": {
+                              "binaryName": "com.github.dart_lang.jnigen.generics.GrandParent",
+                              "typeArguments": [
+                                {
+                                  "kind": "typeVariable",
+                                  "type": {
+                                    "name": "S",
+                                    "nullability": "platform"
+                                  }
+                                }
+                              ],
+                              "nullability": "platform"
+                            }
+                          },
+                          "nullability": "platform"
+                        }
+                      },
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.generics.MyStack",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "S",
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "of()Lcom/github/dart_lang/jnigen/generics/MyStack;": {
+              "name": "of",
+              "typeParameters": [
+                {
+                  "name": "T",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.generics.MyStack",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "T",
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "of(Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/MyStack;": {
+              "name": "of$1",
+              "typeParameters": [
+                {
+                  "name": "T",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "T",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.generics.MyStack",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "T",
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "of(Ljava/lang/Object;Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/MyStack;": {
+              "name": "of$2",
+              "typeParameters": [
+                {
+                  "name": "T",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "T",
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "object1",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "T",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.generics.MyStack",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "T",
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "push(Ljava/lang/Object;)V": {
+              "name": "push",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "T",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "pop()Ljava/lang/Object;": {
+              "name": "pop",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "size()I": {
+              "name": "size",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "T",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        },
+        "com.github.dart_lang.jnigen.generics.StringKeyedMap": {
+          "name": "StringKeyedMap",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "com.github.dart_lang.jnigen.generics.MyMap",
+              "typeArguments": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.String",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                },
+                {
+                  "kind": "typeVariable",
+                  "type": {
+                    "name": "V",
+                    "nullability": "platform"
+                  }
+                }
+              ],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "get(Ljava/lang/Object;)Ljava/lang/Object;": {
+              "name": "get",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;": {
+              "name": "put",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "object1",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "V",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "entryStack()Lcom/github/dart_lang/jnigen/generics/MyStack;": {
+              "name": "entryStack",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.generics.MyStack",
+                  "typeArguments": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "com.github.dart_lang.jnigen.generics.MyMap$MyEntry",
+                        "typeArguments": [
+                          {
+                            "kind": "declared",
+                            "type": {
+                              "binaryName": "java.lang.String",
+                              "typeArguments": [],
+                              "nullability": "platform"
+                            }
+                          },
+                          {
+                            "kind": "typeVariable",
+                            "type": {
+                              "name": "V",
+                              "nullability": "platform"
+                            }
+                          }
+                        ],
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "V",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        },
+        "com.github.dart_lang.jnigen.generics.StringMap": {
+          "name": "StringMap",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "com.github.dart_lang.jnigen.generics.StringKeyedMap",
+              "typeArguments": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.String",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "get(Ljava/lang/String;)Ljava/lang/Object;": {
+              "name": "get",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "put(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;": {
+              "name": "put",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "object1",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "entryStack()Lcom/github/dart_lang/jnigen/generics/MyStack;": {
+              "name": "entryStack",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.generics.MyStack",
+                  "typeArguments": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "com.github.dart_lang.jnigen.generics.MyMap$MyEntry",
+                        "typeArguments": [
+                          {
+                            "kind": "declared",
+                            "type": {
+                              "binaryName": "java.lang.String",
+                              "typeArguments": [],
+                              "nullability": "platform"
+                            }
+                          },
+                          {
+                            "kind": "declared",
+                            "type": {
+                              "binaryName": "java.lang.String",
+                              "typeArguments": [],
+                              "nullability": "platform"
+                            }
+                          }
+                        ],
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.generics.StringStack": {
+          "name": "StringStack",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "com.github.dart_lang.jnigen.generics.MyStack",
+              "typeArguments": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.String",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "push(Ljava/lang/Object;)V": {
+              "name": "push",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "pop()Ljava/lang/Object;": {
+              "name": "pop",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "size()I": {
+              "name": "size",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.generics.StringValuedMap": {
+          "name": "StringValuedMap",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "com.github.dart_lang.jnigen.generics.MyMap",
+              "typeArguments": [
+                {
+                  "kind": "typeVariable",
+                  "type": {
+                    "name": "K",
+                    "nullability": "platform"
+                  }
+                },
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.String",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "get(Ljava/lang/Object;)Ljava/lang/Object;": {
+              "name": "get",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "K",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;": {
+              "name": "put",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "K",
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "object1",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "entryStack()Lcom/github/dart_lang/jnigen/generics/MyStack;": {
+              "name": "entryStack",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.generics.MyStack",
+                  "typeArguments": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "com.github.dart_lang.jnigen.generics.MyMap$MyEntry",
+                        "typeArguments": [
+                          {
+                            "kind": "typeVariable",
+                            "type": {
+                              "name": "K",
+                              "nullability": "platform"
+                            }
+                          },
+                          {
+                            "kind": "declared",
+                            "type": {
+                              "binaryName": "java.lang.String",
+                              "typeArguments": [],
+                              "nullability": "platform"
+                            }
+                          }
+                        ],
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "K",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        },
+        "com.github.dart_lang.jnigen.interfaces.GenericInterface": {
+          "name": "GenericInterface",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "genericArrayOf(Ljava/lang/Object;)[Ljava/lang/Object;": {
+              "name": "genericArrayOf",
+              "typeParameters": [
+                {
+                  "name": "U",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "U",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "elementType": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "U",
+                      "nullability": "platform"
+                    }
+                  },
+                  "nullability": "platform"
+                }
+              }
+            },
+            "arrayOf(Ljava/lang/Object;)[Ljava/lang/Object;": {
+              "name": "arrayOf",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "T",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "elementType": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "T",
+                      "nullability": "platform"
+                    }
+                  },
+                  "nullability": "platform"
+                }
+              }
+            },
+            "mapOf(Ljava/lang/Object;Ljava/lang/Object;)Ljava/util/Map;": {
+              "name": "mapOf",
+              "typeParameters": [
+                {
+                  "name": "U",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "T",
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "object1",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "U",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.Map",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "T",
+                        "nullability": "platform"
+                      }
+                    },
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "U",
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstOfGenericArray([Ljava/lang/Object;)Ljava/lang/Object;": {
+              "name": "firstOfGenericArray",
+              "typeParameters": [
+                {
+                  "name": "U",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "objects",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "elementType": {
+                        "kind": "typeVariable",
+                        "type": {
+                          "name": "U",
+                          "nullability": "platform"
+                        }
+                      },
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "U",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstOfArray([Ljava/lang/Object;)Ljava/lang/Object;": {
+              "name": "firstOfArray",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "objects",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "elementType": {
+                        "kind": "typeVariable",
+                        "type": {
+                          "name": "T",
+                          "nullability": "platform"
+                        }
+                      },
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstKeyOf(Ljava/util/Map;)Ljava/lang/Object;": {
+              "name": "firstKeyOf",
+              "typeParameters": [
+                {
+                  "name": "U",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "map",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.Map",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "platform"
+                          }
+                        },
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "U",
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstValueOf(Ljava/util/Map;)Ljava/lang/Object;": {
+              "name": "firstValueOf",
+              "typeParameters": [
+                {
+                  "name": "U",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "map",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.Map",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "platform"
+                          }
+                        },
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "U",
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "U",
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "T",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        },
+        "com.github.dart_lang.jnigen.interfaces.InheritedFromMyInterface": {
+          "name": "InheritedFromMyInterface",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [
+            {
+              "kind": "declared",
+              "type": {
+                "binaryName": "com.github.dart_lang.jnigen.interfaces.MyInterface",
+                "typeArguments": [
+                  {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                ],
+                "nullability": "platform"
+              }
+            }
+          ],
+          "fields": {},
+          "methods": {
+            "voidCallback(Ljava/lang/String;)V": {
+              "name": "voidCallback",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "stringCallback(Ljava/lang/String;)Ljava/lang/String;": {
+              "name": "stringCallback",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "varCallback(Ljava/lang/Object;)Ljava/lang/Object;": {
+              "name": "varCallback",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "manyPrimitives(IZCD)J": {
+              "name": "manyPrimitives",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "i",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                },
+                {
+                  "name": "c",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "char"
+                    }
+                  }
+                },
+                {
+                  "name": "d",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "double"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "long"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.interfaces.InheritedFromMyRunnable": {
+          "name": "InheritedFromMyRunnable",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [
+            {
+              "kind": "declared",
+              "type": {
+                "binaryName": "com.github.dart_lang.jnigen.interfaces.MyRunnable",
+                "typeArguments": [],
+                "nullability": "platform"
+              }
+            }
+          ],
+          "fields": {},
+          "methods": {
+            "run()V": {
+              "name": "run",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.interfaces.MyInterface": {
+          "name": "MyInterface",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "voidCallback(Ljava/lang/String;)V": {
+              "name": "voidCallback",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "stringCallback(Ljava/lang/String;)Ljava/lang/String;": {
+              "name": "stringCallback",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "varCallback(Ljava/lang/Object;)Ljava/lang/Object;": {
+              "name": "varCallback",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "T",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "manyPrimitives(IZCD)J": {
+              "name": "manyPrimitives",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "i",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                },
+                {
+                  "name": "c",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "char"
+                    }
+                  }
+                },
+                {
+                  "name": "d",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "double"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "long"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "T",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        },
+        "com.github.dart_lang.jnigen.interfaces.MyInterfaceConsumer": {
+          "name": "MyInterfaceConsumer",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "consumeOnAnotherThread(Lcom/github/dart_lang/jnigen/interfaces/MyInterface;Ljava/lang/String;IZCDLjava/lang/Object;)V": {
+              "name": "consumeOnAnotherThread",
+              "typeParameters": [
+                {
+                  "name": "T",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "myInterface",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "com.github.dart_lang.jnigen.interfaces.MyInterface",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "i",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                },
+                {
+                  "name": "c",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "char"
+                    }
+                  }
+                },
+                {
+                  "name": "d",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "double"
+                    }
+                  }
+                },
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "T",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "consumeOnSameThread(Lcom/github/dart_lang/jnigen/interfaces/MyInterface;Ljava/lang/String;IZCDLjava/lang/Object;)V": {
+              "name": "consumeOnSameThread",
+              "typeParameters": [
+                {
+                  "name": "T",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "myInterface",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "com.github.dart_lang.jnigen.interfaces.MyInterface",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "i",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                },
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                },
+                {
+                  "name": "c",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "char"
+                    }
+                  }
+                },
+                {
+                  "name": "d",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "double"
+                    }
+                  }
+                },
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "T",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.interfaces.MyRunnable": {
+          "name": "MyRunnable",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "run()V": {
+              "name": "run",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.interfaces.MyRunnableRunner": {
+          "name": "MyRunnableRunner",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "runnable": {
+              "name": "runnable",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.interfaces.MyRunnable",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "error": {
+              "name": "error",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.Throwable",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "methods": {
+            "<init>(Lcom/github/dart_lang/jnigen/interfaces/MyRunnable;)V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "myRunnable",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "com.github.dart_lang.jnigen.interfaces.MyRunnable",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "runOnSameThread()V": {
+              "name": "runOnSameThread",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "runOnAnotherThread()V": {
+              "name": "runOnAnotherThread",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "runOnAnotherThreadAndJoin()V": {
+              "name": "runOnAnotherThreadAndJoin",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.interfaces.StringConversionException": {
+          "name": "StringConversionException",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Exception",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "<init>(Ljava/lang/String;)V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.interfaces.StringConverter": {
+          "name": "StringConverter",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "parseToInt(Ljava/lang/String;)I": {
+              "name": "parseToInt",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "int"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.interfaces.StringConverterConsumer": {
+          "name": "StringConverterConsumer",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "consumeOnSameThread(Lcom/github/dart_lang/jnigen/interfaces/StringConverter;Ljava/lang/String;)Ljava/lang/Integer;": {
+              "name": "consumeOnSameThread",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "stringConverter",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "com.github.dart_lang.jnigen.interfaces.StringConverter",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.Integer",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "consumeOnAnotherThread(Lcom/github/dart_lang/jnigen/interfaces/StringConverter;Ljava/lang/String;)Ljava/util/concurrent/Future;": {
+              "name": "consumeOnAnotherThread",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "stringConverter",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "com.github.dart_lang.jnigen.interfaces.StringConverter",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.concurrent.Future",
+                  "typeArguments": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Integer",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.inheritance.BaseClass": {
+          "name": "BaseClass",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "T",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.CharSequence",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        },
+        "com.github.dart_lang.jnigen.inheritance.BaseGenericInterface": {
+          "name": "BaseGenericInterface",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "foo()Ljava/lang/Object;": {
+              "name": "foo",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "T",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        },
+        "com.github.dart_lang.jnigen.inheritance.BaseInterface": {
+          "name": "BaseInterface",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "foo()Ljava/lang/String;": {
+              "name": "foo",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.inheritance.DerivedInterface": {
+          "name": "DerivedInterface",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [
+            {
+              "kind": "declared",
+              "type": {
+                "binaryName": "com.github.dart_lang.jnigen.inheritance.BaseGenericInterface",
+                "typeArguments": [
+                  {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                ],
+                "nullability": "platform"
+              }
+            },
+            {
+              "kind": "declared",
+              "type": {
+                "binaryName": "com.github.dart_lang.jnigen.inheritance.BaseInterface",
+                "typeArguments": [],
+                "nullability": "platform"
+              }
+            }
+          ],
+          "fields": {},
+          "methods": {
+            "foo()Ljava/lang/String;": {
+              "name": "foo",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "foo()Ljava/lang/Object;": {
+              "name": "foo",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.Object",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.inheritance.GenericDerivedClass": {
+          "name": "GenericDerivedClass",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "com.github.dart_lang.jnigen.inheritance.BaseClass",
+              "typeArguments": [
+                {
+                  "kind": "typeVariable",
+                  "type": {
+                    "name": "T",
+                    "nullability": "platform"
+                  }
+                }
+              ],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "T",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.CharSequence",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        },
+        "com.github.dart_lang.jnigen.inheritance.SpecificDerivedClass": {
+          "name": "SpecificDerivedClass",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "com.github.dart_lang.jnigen.inheritance.BaseClass",
+              "typeArguments": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.String",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.annotations.Annotated$Nested": {
+          "name": "Annotated$Nested",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "v": {
+              "name": "v",
+              "type": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "u": {
+              "name": "u",
+              "type": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "U",
+                  "nullability": "nonNullable"
+                }
+              }
+            }
+          },
+          "methods": {
+            "<init>(Lcom/github/dart_lang/jnigen/annotations/Annotated;Ljava/lang/Object;)V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "$$outerClass",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "com.github.dart_lang.jnigen.annotations.Annotated",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "platform"
+                          }
+                        },
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "U",
+                            "nullability": "nonNullable"
+                          }
+                        },
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "W",
+                            "nullability": "nonNullable"
+                          }
+                        }
+                      ],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                },
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "V",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "T",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            },
+            {
+              "name": "U",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "nonNullable"
+                  }
+                }
+              ]
+            },
+            {
+              "name": "W",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            },
+            {
+              "name": "V",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        },
+        "com.github.dart_lang.jnigen.annotations.Annotated": {
+          "name": "Annotated",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "t": {
+              "name": "t",
+              "type": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "u": {
+              "name": "u",
+              "type": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "U",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "w": {
+              "name": "w",
+              "type": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "W",
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "methods": {
+            "<init>(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "T",
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "object1",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "U",
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "object2",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "W",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "staticHello()Ljava/lang/String;": {
+              "name": "staticHello",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "hello()Ljava/lang/String;": {
+              "name": "hello",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "nullableHello(Z)Ljava/lang/String;": {
+              "name": "nullableHello",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "echo(Ljava/lang/String;)Ljava/lang/String;": {
+              "name": "echo",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "nullableEcho(Ljava/lang/String;)Ljava/lang/String;": {
+              "name": "nullableEcho",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.lang.String",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "array()[Ljava/lang/String;": {
+              "name": "array",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "elementType": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "nonNullable"
+                    }
+                  },
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "arrayOfNullable()[Ljava/lang/String;": {
+              "name": "arrayOfNullable",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "elementType": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  },
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "nullableArray(Z)[Ljava/lang/String;": {
+              "name": "nullableArray",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "elementType": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "nonNullable"
+                    }
+                  },
+                  "nullability": "platform"
+                }
+              }
+            },
+            "nullableArrayOfNullable(Z)[Ljava/lang/String;": {
+              "name": "nullableArrayOfNullable",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "elementType": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  },
+                  "nullability": "platform"
+                }
+              }
+            },
+            "list()Ljava/util/List;": {
+              "name": "list",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.List",
+                  "typeArguments": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.String",
+                        "typeArguments": [],
+                        "nullability": "nonNullable"
+                      }
+                    }
+                  ],
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "listOfNullable()Ljava/util/List;": {
+              "name": "listOfNullable",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.List",
+                  "typeArguments": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.String",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "nullableList(Z)Ljava/util/List;": {
+              "name": "nullableList",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.List",
+                  "typeArguments": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.String",
+                        "typeArguments": [],
+                        "nullability": "nonNullable"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "nullableListOfNullable(Z)Ljava/util/List;": {
+              "name": "nullableListOfNullable",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.List",
+                  "typeArguments": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.String",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "classGenericEcho(Ljava/lang/Object;)Ljava/lang/Object;": {
+              "name": "classGenericEcho",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "T",
+                      "nullability": "nonNullable"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "nullableClassGenericEcho(Ljava/lang/Object;)Ljava/lang/Object;": {
+              "name": "nullableClassGenericEcho",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "T",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "methodGenericEcho(Ljava/lang/Object;)Ljava/lang/Object;": {
+              "name": "methodGenericEcho",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "V",
+                      "nullability": "nonNullable"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "methodGenericEcho2(Ljava/lang/Object;)Ljava/lang/Object;": {
+              "name": "methodGenericEcho2",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "V",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "methodGenericEcho3(Ljava/lang/Object;)Ljava/lang/Object;": {
+              "name": "methodGenericEcho3",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "nonNullable"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "V",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "nullableReturnMethodGenericEcho(Ljava/lang/Object;Z)Ljava/lang/Object;": {
+              "name": "nullableReturnMethodGenericEcho",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "V",
+                      "nullability": "nonNullable"
+                    }
+                  }
+                },
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "nullableReturnMethodGenericEcho2(Ljava/lang/Object;Z)Ljava/lang/Object;": {
+              "name": "nullableReturnMethodGenericEcho2",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "V",
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "nullable"
+                }
+              }
+            },
+            "nullableMethodGenericEcho(Ljava/lang/Object;)Ljava/lang/Object;": {
+              "name": "nullableMethodGenericEcho",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "V",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "noAnnotationMethodGenericEcho(Ljava/lang/Object;)Ljava/lang/Object;": {
+              "name": "noAnnotationMethodGenericEcho",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "V",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "nullableArgMethodGenericEcho(Ljava/lang/Object;)Ljava/lang/Object;": {
+              "name": "nullableArgMethodGenericEcho",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "V",
+                      "nullability": "nullable"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "classGenericList()Ljava/util/List;": {
+              "name": "classGenericList",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.List",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "T",
+                        "nullability": "nonNullable"
+                      }
+                    }
+                  ],
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "classGenericListOfNullable()Ljava/util/List;": {
+              "name": "classGenericListOfNullable",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.List",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "T",
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "nullableClassGenericList(Z)Ljava/util/List;": {
+              "name": "nullableClassGenericList",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.List",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "T",
+                        "nullability": "nonNullable"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "nullableClassGenericListOfNullable(Z)Ljava/util/List;": {
+              "name": "nullableClassGenericListOfNullable",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.List",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "T",
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "methodGenericList(Ljava/lang/Object;)Ljava/util/List;": {
+              "name": "methodGenericList",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "V",
+                      "nullability": "nonNullable"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.List",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "V",
+                        "nullability": "nonNullable"
+                      }
+                    }
+                  ],
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "methodGenericListOfNullable()Ljava/util/List;": {
+              "name": "methodGenericListOfNullable",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.List",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "V",
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "nullableMethodGenericList(Ljava/lang/Object;Z)Ljava/util/List;": {
+              "name": "nullableMethodGenericList",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "V",
+                      "nullability": "nonNullable"
+                    }
+                  }
+                },
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.List",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "V",
+                        "nullability": "nonNullable"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "nullableMethodGenericListOfNullable(Z)Ljava/util/List;": {
+              "name": "nullableMethodGenericListOfNullable",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.List",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "V",
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstOfClassGenericList(Ljava/util/List;)Ljava/lang/Object;": {
+              "name": "firstOfClassGenericList",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "list",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.List",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "nonNullable"
+                          }
+                        }
+                      ],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstOfClassGenericNullableList(Ljava/util/List;)Ljava/lang/Object;": {
+              "name": "firstOfClassGenericNullableList",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "list",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.List",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "nonNullable"
+                          }
+                        }
+                      ],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstOfClassGenericListOfNullable(Ljava/util/List;)Ljava/lang/Object;": {
+              "name": "firstOfClassGenericListOfNullable",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "list",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.List",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstOfClassGenericNullableListOfNullable(Ljava/util/List;)Ljava/lang/Object;": {
+              "name": "firstOfClassGenericNullableListOfNullable",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "list",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.List",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstOfMethodGenericList(Ljava/util/List;)Ljava/lang/Object;": {
+              "name": "firstOfMethodGenericList",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "list",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.List",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "V",
+                            "nullability": "nonNullable"
+                          }
+                        }
+                      ],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstOfMethodGenericNullableList(Ljava/util/List;)Ljava/lang/Object;": {
+              "name": "firstOfMethodGenericNullableList",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "list",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.List",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "V",
+                            "nullability": "nonNullable"
+                          }
+                        }
+                      ],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstOfMethodGenericListOfNullable(Ljava/util/List;)Ljava/lang/Object;": {
+              "name": "firstOfMethodGenericListOfNullable",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "list",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.List",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "V",
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstOfMethodGenericNullableListOfNullable(Ljava/util/List;)Ljava/lang/Object;": {
+              "name": "firstOfMethodGenericNullableListOfNullable",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "list",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.List",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "V",
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstKeyOfComboMap(Ljava/util/Map;)Ljava/lang/Object;": {
+              "name": "firstKeyOfComboMap",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "map",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.Map",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "nonNullable"
+                          }
+                        },
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "V",
+                            "nullability": "nonNullable"
+                          }
+                        }
+                      ],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstValueOfComboMap(Ljava/util/Map;)Ljava/lang/Object;": {
+              "name": "firstValueOfComboMap",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "map",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.Map",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "nonNullable"
+                          }
+                        },
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "V",
+                            "nullability": "nonNullable"
+                          }
+                        }
+                      ],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstKeyOfComboMapNullableKey(Ljava/util/Map;)Ljava/lang/Object;": {
+              "name": "firstKeyOfComboMapNullableKey",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "map",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.Map",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "platform"
+                          }
+                        },
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "V",
+                            "nullability": "nonNullable"
+                          }
+                        }
+                      ],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstValueOfComboMapNullableKey(Ljava/util/Map;)Ljava/lang/Object;": {
+              "name": "firstValueOfComboMapNullableKey",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "map",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.Map",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "platform"
+                          }
+                        },
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "V",
+                            "nullability": "nonNullable"
+                          }
+                        }
+                      ],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstKeyOfComboMapNullableValue(Ljava/util/Map;)Ljava/lang/Object;": {
+              "name": "firstKeyOfComboMapNullableValue",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "map",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.Map",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "nonNullable"
+                          }
+                        },
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "V",
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstValueOfComboMapNullableValue(Ljava/util/Map;)Ljava/lang/Object;": {
+              "name": "firstValueOfComboMapNullableValue",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "map",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.Map",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "nonNullable"
+                          }
+                        },
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "V",
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstKeyOfComboMapNullableKeyAndValue(Ljava/util/Map;)Ljava/lang/Object;": {
+              "name": "firstKeyOfComboMapNullableKeyAndValue",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "map",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.Map",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "platform"
+                          }
+                        },
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "V",
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstValueOfComboMapNullableKeyAndValue(Ljava/util/Map;)Ljava/lang/Object;": {
+              "name": "firstValueOfComboMapNullableKeyAndValue",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "map",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.Map",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "platform"
+                          }
+                        },
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "V",
+                            "nullability": "platform"
+                          }
+                        }
+                      ],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "V",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "firstEntryOfComboMap(Ljava/util/Map;)Ljava/util/Map$Entry;": {
+              "name": "firstEntryOfComboMap",
+              "typeParameters": [
+                {
+                  "name": "V",
+                  "bounds": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Object",
+                        "typeArguments": [],
+                        "nullability": "platform"
+                      }
+                    }
+                  ]
+                }
+              ],
+              "methodParameters": [
+                {
+                  "name": "map",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.util.Map",
+                      "typeArguments": [
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "T",
+                            "nullability": "nonNullable"
+                          }
+                        },
+                        {
+                          "kind": "typeVariable",
+                          "type": {
+                            "name": "V",
+                            "nullability": "nonNullable"
+                          }
+                        }
+                      ],
+                      "nullability": "nonNullable"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.Map$Entry",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "T",
+                        "nullability": "nonNullable"
+                      }
+                    },
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "V",
+                        "nullability": "nonNullable"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "getW()Ljava/lang/Object;": {
+              "name": "getW",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "W",
+                  "nullability": "platform"
+                }
+              }
+            },
+            "nullableGetW(Z)Ljava/lang/Object;": {
+              "name": "nullableGetW",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "W",
+                  "nullability": "nullable"
+                }
+              }
+            },
+            "list3dOfT()Ljava/util/List;": {
+              "name": "list3dOfT",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.List",
+                  "typeArguments": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.util.List",
+                        "typeArguments": [
+                          {
+                            "kind": "declared",
+                            "type": {
+                              "binaryName": "java.util.List",
+                              "typeArguments": [
+                                {
+                                  "kind": "typeVariable",
+                                  "type": {
+                                    "name": "T",
+                                    "nullability": "platform"
+                                  }
+                                }
+                              ],
+                              "nullability": "nonNullable"
+                            }
+                          }
+                        ],
+                        "nullability": "nonNullable"
+                      }
+                    }
+                  ],
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "list3dOfU()Ljava/util/List;": {
+              "name": "list3dOfU",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.List",
+                  "typeArguments": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.util.List",
+                        "typeArguments": [
+                          {
+                            "kind": "declared",
+                            "type": {
+                              "binaryName": "java.util.List",
+                              "typeArguments": [
+                                {
+                                  "kind": "typeVariable",
+                                  "type": {
+                                    "name": "U",
+                                    "nullability": "platform"
+                                  }
+                                }
+                              ],
+                              "nullability": "nonNullable"
+                            }
+                          }
+                        ],
+                        "nullability": "nonNullable"
+                      }
+                    }
+                  ],
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "list3dOfW()Ljava/util/List;": {
+              "name": "list3dOfW",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.List",
+                  "typeArguments": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.util.List",
+                        "typeArguments": [
+                          {
+                            "kind": "declared",
+                            "type": {
+                              "binaryName": "java.util.List",
+                              "typeArguments": [
+                                {
+                                  "kind": "typeVariable",
+                                  "type": {
+                                    "name": "W",
+                                    "nullability": "platform"
+                                  }
+                                }
+                              ],
+                              "nullability": "nonNullable"
+                            }
+                          }
+                        ],
+                        "nullability": "nonNullable"
+                      }
+                    }
+                  ],
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "list3dOfNullableU(Z)Ljava/util/List;": {
+              "name": "list3dOfNullableU",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.List",
+                  "typeArguments": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.util.List",
+                        "typeArguments": [
+                          {
+                            "kind": "declared",
+                            "type": {
+                              "binaryName": "java.util.List",
+                              "typeArguments": [
+                                {
+                                  "kind": "typeVariable",
+                                  "type": {
+                                    "name": "U",
+                                    "nullability": "nullable"
+                                  }
+                                }
+                              ],
+                              "nullability": "nonNullable"
+                            }
+                          }
+                        ],
+                        "nullability": "nonNullable"
+                      }
+                    }
+                  ],
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "list3dOfNullableW(Z)Ljava/util/List;": {
+              "name": "list3dOfNullableW",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "z",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "boolean"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.List",
+                  "typeArguments": [
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.util.List",
+                        "typeArguments": [
+                          {
+                            "kind": "declared",
+                            "type": {
+                              "binaryName": "java.util.List",
+                              "typeArguments": [
+                                {
+                                  "kind": "typeVariable",
+                                  "type": {
+                                    "name": "W",
+                                    "nullability": "nullable"
+                                  }
+                                }
+                              ],
+                              "nullability": "nonNullable"
+                            }
+                          }
+                        ],
+                        "nullability": "nonNullable"
+                      }
+                    }
+                  ],
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "nested()Lcom/github/dart_lang/jnigen/annotations/Annotated$Nested;": {
+              "name": "nested",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.annotations.Annotated$Nested",
+                  "typeArguments": [
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "T",
+                        "nullability": "platform"
+                      }
+                    },
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "U",
+                        "nullability": "platform"
+                      }
+                    },
+                    {
+                      "kind": "typeVariable",
+                      "type": {
+                        "name": "W",
+                        "nullability": "platform"
+                      }
+                    },
+                    {
+                      "kind": "declared",
+                      "type": {
+                        "binaryName": "java.lang.Integer",
+                        "typeArguments": [],
+                        "nullability": "nonNullable"
+                      }
+                    }
+                  ],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "intList()Ljava/util/List;": {
+              "name": "intList",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "java.util.List",
+                  "typeArguments": [
+                    {
+                      "kind": "wildcard",
+                      "type": {
+                        "extendsBound": {
+                          "kind": "declared",
+                          "type": {
+                            "binaryName": "java.lang.Integer",
+                            "typeArguments": [],
+                            "nullability": "nonNullable"
+                          }
+                        },
+                        "superBound": null,
+                        "nullability": "platform"
+                      }
+                    }
+                  ],
+                  "nullability": "nonNullable"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "T",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            },
+            {
+              "name": "U",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "nonNullable"
+                  }
+                }
+              ]
+            },
+            {
+              "name": "W",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        },
+        "com.github.dart_lang.jnigen.annotations.JsonSerializable$Case": {
+          "name": "JsonSerializable$Case",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Enum",
+              "typeArguments": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "com.github.dart_lang.jnigen.annotations.JsonSerializable$Case",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {
+            "SNAKE_CASE": {
+              "name": "SNAKE_CASE",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.annotations.JsonSerializable$Case",
+                  "typeArguments": [],
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "KEBAB_CASE": {
+              "name": "KEBAB_CASE",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.annotations.JsonSerializable$Case",
+                  "typeArguments": [],
+                  "nullability": "nonNullable"
+                }
+              }
+            },
+            "CAMEL_CASE": {
+              "name": "CAMEL_CASE",
+              "type": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.annotations.JsonSerializable$Case",
+                  "typeArguments": [],
+                  "nullability": "nonNullable"
+                }
+              }
+            }
+          },
+          "methods": {
+            "values()[Lcom/github/dart_lang/jnigen/annotations/JsonSerializable$Case;": {
+              "name": "values",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "elementType": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "com.github.dart_lang.jnigen.annotations.JsonSerializable$Case",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  },
+                  "nullability": "platform"
+                }
+              }
+            },
+            "valueOf(Ljava/lang/String;)Lcom/github/dart_lang/jnigen/annotations/JsonSerializable$Case;": {
+              "name": "valueOf",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.annotations.JsonSerializable$Case",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "<init>(Ljava/lang/String;I)V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "string",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.String",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                },
+                {
+                  "name": "i",
+                  "type": {
+                    "kind": "primitive",
+                    "type": {
+                      "name": "int"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "<clinit>()V": {
+              "name": "$_clinit_",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.annotations.JsonSerializable": {
+          "name": "JsonSerializable",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [
+            {
+              "kind": "declared",
+              "type": {
+                "binaryName": "java.lang.annotation.Annotation",
+                "typeArguments": [],
+                "nullability": "platform"
+              }
+            }
+          ],
+          "fields": {},
+          "methods": {
+            "value()Lcom/github/dart_lang/jnigen/annotations/JsonSerializable$Case;": {
+              "name": "value",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.annotations.JsonSerializable$Case",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.annotations.MyDataClass": {
+          "name": "MyDataClass",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.annotations.NotNull": {
+          "name": "NotNull",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [
+            {
+              "kind": "declared",
+              "type": {
+                "binaryName": "java.lang.annotation.Annotation",
+                "typeArguments": [],
+                "nullability": "platform"
+              }
+            }
+          ],
+          "fields": {},
+          "methods": {},
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.annotations.Nullable": {
+          "name": "Nullable",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [
+            {
+              "kind": "declared",
+              "type": {
+                "binaryName": "java.lang.annotation.Annotation",
+                "typeArguments": [],
+                "nullability": "platform"
+              }
+            }
+          ],
+          "fields": {},
+          "methods": {},
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.regressions.R2250$Child": {
+          "name": "R2250$Child",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [
+            {
+              "kind": "declared",
+              "type": {
+                "binaryName": "com.github.dart_lang.jnigen.regressions.R2250",
+                "typeArguments": [],
+                "nullability": "platform"
+              }
+            }
+          ],
+          "fields": {},
+          "methods": {
+            "foo(Ljava/lang/Object;)V": {
+              "name": "foo",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "declared",
+                    "type": {
+                      "binaryName": "java.lang.Object",
+                      "typeArguments": [],
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.regressions.R2250": {
+          "name": "R2250",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "foo(Ljava/lang/Object;)V": {
+              "name": "foo",
+              "typeParameters": [],
+              "methodParameters": [
+                {
+                  "name": "object",
+                  "type": {
+                    "kind": "typeVariable",
+                    "type": {
+                      "name": "T",
+                      "nullability": "platform"
+                    }
+                  }
+                }
+              ],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "T",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "java.lang.Object",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        },
+        "com.github.dart_lang.jnigen.regressions.R693$Child": {
+          "name": "R693$Child",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "com.github.dart_lang.jnigen.regressions.R693",
+              "typeArguments": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "com.github.dart_lang.jnigen.regressions.R693$Child",
+                    "typeArguments": [],
+                    "nullability": "platform"
+                  }
+                }
+              ],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "foo()Lcom/github/dart_lang/jnigen/regressions/R693$Child;": {
+              "name": "foo$1",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.regressions.R693$Child",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            },
+            "foo()Lcom/github/dart_lang/jnigen/regressions/R693;": {
+              "name": "foo",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "declared",
+                "type": {
+                  "binaryName": "com.github.dart_lang.jnigen.regressions.R693",
+                  "typeArguments": [],
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "typeParameters": []
+        },
+        "com.github.dart_lang.jnigen.regressions.R693": {
+          "name": "R693",
+          "superClass": {
+            "kind": "declared",
+            "type": {
+              "binaryName": "java.lang.Object",
+              "typeArguments": [],
+              "nullability": "platform"
+            }
+          },
+          "superInterfaces": [],
+          "fields": {},
+          "methods": {
+            "<init>()V": {
+              "name": "new$",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "primitive",
+                "type": {
+                  "name": "void"
+                }
+              }
+            },
+            "foo()Lcom/github/dart_lang/jnigen/regressions/R693;": {
+              "name": "foo",
+              "typeParameters": [],
+              "methodParameters": [],
+              "returnType": {
+                "kind": "typeVariable",
+                "type": {
+                  "name": "T",
+                  "nullability": "platform"
+                }
+              }
+            }
+          },
+          "typeParameters": [
+            {
+              "name": "T",
+              "bounds": [
+                {
+                  "kind": "declared",
+                  "type": {
+                    "binaryName": "com.github.dart_lang.jnigen.regressions.R693",
+                    "typeArguments": [
+                      {
+                        "kind": "typeVariable",
+                        "type": {
+                          "name": "T",
+                          "nullability": "platform"
+                        }
+                      }
+                    ],
+                    "nullability": "platform"
+                  }
+                }
+              ]
+            }
+          ]
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/pkgs/jnigen/lib/src/bindings/dart_generator.dart b/pkgs/jnigen/lib/src/bindings/dart_generator.dart
index bee93d0..324eb48 100644
--- a/pkgs/jnigen/lib/src/bindings/dart_generator.dart
+++ b/pkgs/jnigen/lib/src/bindings/dart_generator.dart
@@ -6,12 +6,12 @@
 import 'dart:io';
 
 import 'package:meta/meta.dart';
+import 'package:path/path.dart' as p;
 
 import '../config/config.dart';
 import '../elements/elements.dart';
 import '../logging/logging.dart';
 import '../util/string_util.dart';
-import 'resolver.dart';
 import 'visitor.dart';
 
 /// Version of jnigen. Keep in sync with `pubspec.yaml` removing the `-wip`
@@ -135,11 +135,60 @@
 ///   calling, or whenever we don't want to have the `extends` keyword.
 /// * `fTypeClassesDef` refers to `JType<T> $T, JType<U> $U`.
 /// * `fTypeClassesCall` refers to `$T, $U` when calling the method.
-class DartGenerator extends Visitor<Classes, Future<void>> {
+class DartGenerator extends ElementVisitor<Classes, Future<void>>
+    with TopLevelVisitor {
+  @override
+  final stage = GenerationStage.dartGenerator;
+
   final Config config;
 
   DartGenerator(this.config);
 
+  @override
+  Future<void> visit(Classes node) async {
+    final fileGenerator = _FileGenerator(config);
+    await node.files.values.accept(fileGenerator).wait;
+    log.finest('Generated the bindings successfully.');
+
+    if (config.outputConfig.dartConfig.structure ==
+        OutputStructure.singleFile) {
+      return;
+    }
+
+    final root = config.outputConfig.dartConfig.path;
+    log.info('Using dart root = $root');
+    {
+      final rootDirectory = Directory.fromUri(root);
+      if (rootDirectory.existsSync()) {
+        final files = rootDirectory.listSync(recursive: true).whereType<File>();
+        final filesToRemove = <File>[];
+        for (final file in files) {
+          final stream = file.openRead();
+          final firstLine = await stream
+              .transform(const Utf8Decoder())
+              .transform(const LineSplitter())
+              .first;
+          if (firstLine.startsWith('// AUTO GENERATED BY JNIGEN ')) {
+            log.fine('Removing old file ${file.path}');
+            filesToRemove.add(file);
+          } else {
+            throw StateError('''
+A file that was not generated by JNIgen was found in ${root.path}: ${file.path}.''');
+          }
+        }
+        await filesToRemove.map((file) => file.delete()).wait;
+      }
+    }
+  }
+}
+
+typedef Resolver = String? Function(ClassDecl);
+
+class _FileGenerator extends ElementVisitor<DartFile, Future<void>> {
+  final Config config;
+
+  _FileGenerator(this.config);
+
   // Do not change this.
   static const autoGeneratedNotice = '// AUTO GENERATED BY JNIGEN $version. '
       'DO NOT EDIT!\n';
@@ -148,7 +197,6 @@
 import 'dart:core' as $_core;
 
 import 'package:jni/_internal.dart' as $_jni;
-import 'package:jni/jni.dart' as $_jni;
 
 ''';
 
@@ -202,116 +250,57 @@
   }
 
   @override
-  Future<void> visit(Classes node) async {
-    final root = config.outputConfig.dartConfig.path;
+  Future<void> visit(DartFile node) async {
+    log.warning(node.path);
+    final dartFile =
+        await File.fromUri(Uri.parse(node.path)).create(recursive: true);
     final preamble = config.preamble ?? '';
-    if (config.outputConfig.dartConfig.structure ==
-        OutputStructure.singleFile) {
-      final file = File.fromUri(root);
-      await file.create(recursive: true);
-      log.info('Generating bindings');
-      final s = file.openWrite();
-      s.writeln(autoGeneratedNotice);
-      s.writeln(preamble);
-      s.writeln(defaultLintSuppressions);
-      s.writeln(defaultImports);
-      final resolver = Resolver(
-        importedClasses: config.importedClasses,
-        currentClass: null, // Single file mode.
-        inputClassNames: node.decls.keys.toSet(),
-      );
-      final classGenerator = _ClassGenerator(config, s, resolver);
-      for (final classDecl in node.decls.values) {
-        classDecl.accept(classGenerator);
-      }
-      await s.close();
-      await _runDartFormat(file.path);
-      return;
+    final dartFileStream = dartFile.openWrite();
+    dartFileStream.writeln(autoGeneratedNotice);
+    dartFileStream.writeln(preamble);
+    dartFileStream.writeln(defaultLintSuppressions);
+    dartFileStream.writeln(defaultImports);
+    for (final exportedFile in node.exports) {
+      final path = p.relative(exportedFile.path, from: node.path);
+      dartFileStream.writeln("export '$path';");
     }
-    final files = <String, List<ClassDecl>>{};
-    final packages = <String, Set<String>>{};
-    for (final classDecl in node.decls.values) {
-      final fileClass = Resolver.getFileClassName(classDecl.binaryName);
+    final s = StringBuffer();
 
-      files.putIfAbsent(fileClass, () => <ClassDecl>[]);
-      files[fileClass]!.add(classDecl);
-
-      packages.putIfAbsent(classDecl.packageName, () => {});
-      packages[classDecl.packageName]!.add(fileClass.split('.').last);
+    /// A map from the binary names of the imported classes to their import
+    /// prefix.
+    final fileToImportPrefix = <DartFile, String>{
+      DeclaredType.object.classDecl.file: _jni,
+    };
+    String importPrefix(ClassDecl classDecl) {
+      if (classDecl.file == node) return '';
+      fileToImportPrefix[classDecl.file] ??= 'i${fileToImportPrefix.length}\$_';
+      return '${fileToImportPrefix[classDecl.file]}.';
     }
 
-    log.info('Using dart root = $root');
-    {
-      final rootDirectory = Directory.fromUri(root);
-      if (rootDirectory.existsSync()) {
-        final files = rootDirectory.listSync(recursive: true).whereType<File>();
-        final filesToRemove = <File>[];
-        for (final file in files) {
-          final stream = file.openRead();
-          final firstLine = await stream
-              .transform(const Utf8Decoder())
-              .transform(const LineSplitter())
-              .first;
-          if (firstLine.startsWith('// AUTO GENERATED BY JNIGEN ')) {
-            log.fine('Removing old file ${file.path}');
-            filesToRemove.add(file);
-          } else {
-            throw StateError('''
-A file that was not generated by JNIgen was found in ${root.path}: ${file.path}.''');
-          }
-        }
-        await filesToRemove.map((file) => file.delete()).wait;
-      }
+    final classGenerator = _ClassGenerator(config, s, importPrefix);
+    for (final classDecl in node.classes.values) {
+      classDecl.accept(classGenerator);
     }
-    for (var fileClassName in files.keys) {
-      final relativeFileName = '${fileClassName.replaceAll('.', '/')}.dart';
-      final dartFileUri = root.resolve(relativeFileName);
-      final dartFile = await File.fromUri(dartFileUri).create(recursive: true);
-      log.fine('$fileClassName -> ${dartFile.path}');
-
-      final classesInFile = files[fileClassName]!;
-      final dartFileStream = dartFile.openWrite();
-      dartFileStream.writeln(autoGeneratedNotice);
-      dartFileStream.writeln(preamble);
-      dartFileStream.writeln(defaultLintSuppressions);
-      dartFileStream.writeln(defaultImports);
-      final s = StringBuffer();
-      final resolver = Resolver(
-        importedClasses: config.importedClasses,
-        currentClass: fileClassName,
-        inputClassNames: node.decls.keys.toSet(),
-      );
-      final classGenerator = _ClassGenerator(config, s, resolver);
-      for (final classDecl in classesInFile) {
-        classDecl.accept(classGenerator);
-      }
-      dartFileStream.writeAll(resolver.importStrings, '\n');
-      dartFileStream.writeln(s.toString());
-      await dartFileStream.close();
+    for (final MapEntry(key: importFile, value: importPrefix)
+        in fileToImportPrefix.entries) {
+      dartFileStream.writeln("import '${importFile.path}' as $importPrefix;");
     }
-
-    // write _package.dart export files
-    for (var package in packages.keys) {
-      final dirUri = root.resolve('${package.replaceAll('.', '/')}/');
-      final exportFileUri = dirUri.resolve('_package.dart');
-      final exportFile = File.fromUri(exportFileUri);
-      exportFile.createSync(recursive: true);
-      final exports =
-          packages[package]!.map((cls) => "export '$cls.dart';").join('\n');
-      exportFile.writeAsStringSync(autoGeneratedNotice + exports);
-    }
-    await _runDartFormat(root.toFilePath());
-    log.info('Completed.');
+    dartFileStream.writeln(s.toString());
+    await dartFileStream.close();
+    await _runDartFormat(node.path);
   }
 }
 
-/// Generates the Dart class definition, type class, and the array extension.
-class _ClassGenerator extends Visitor<ClassDecl, void> {
+/// Generates the Dart class definition and type class.
+///
+/// In case of interfaces it also generates the classes related to interface
+/// implementation.
+class _ClassGenerator extends ElementVisitor<ClassDecl, void> {
   final Config config;
   final StringSink s;
-  final Resolver resolver;
+  final Resolver resolve;
 
-  _ClassGenerator(this.config, this.s, this.resolver);
+  _ClassGenerator(this.config, this.s, this.resolve);
 
   static const staticTypeGetter = 'type';
   static const instanceTypeGetter = '\$$staticTypeGetter';
@@ -319,7 +308,7 @@
   void generateFieldsAndMethods(ClassDecl node, String classRef) {
     final fieldGenerator = _FieldGenerator(
       config,
-      resolver,
+      resolve,
       s,
       isTopLevel: node.isTopLevel,
       classRef: classRef,
@@ -329,7 +318,7 @@
     }
     final methodGenerator = _MethodGenerator(
       config,
-      resolver,
+      resolve,
       s,
       isTopLevel: node.isTopLevel,
       classRef: classRef,
@@ -365,7 +354,7 @@
     // Class definition.
     final name = node.finalName;
     final superName = node.superclass!.accept(
-      _TypeGenerator(resolver, includeNullability: false),
+      _TypeGenerator(resolve, includeNullability: false),
     );
     final implClassName = '\$$name';
     final typeParamsDef = node.allTypeParams
@@ -390,11 +379,11 @@
     final ctorTypeClassesDef = typeParams
         .map((typeParam) => 'this.$typeParam,')
         .join(_newLine(depth: 2));
-    final superClass = node.classDecl.superclass! as DeclaredType;
+    final superClass = node.superclass! as DeclaredType;
     final superTypeClassesCall = superClass.classDecl.isObject
         ? ''
         : superClass.params
-            .accept(_TypeClassGenerator(resolver))
+            .accept(_TypeClassGenerator(resolve))
             .map((typeClass) => '${typeClass.name},')
             .join(_newLine(depth: 2));
     s.write('''
@@ -465,9 +454,9 @@
     // Operators
     for (final MapEntry(key: operator, value: method)
         in node.operators.entries) {
-      method.accept(_OperatorGenerator(resolver, s, operator: operator));
+      method.accept(_OperatorGenerator(resolve, s, operator: operator));
     }
-    node.compareTo?.accept(_ComparatorGenerator(resolver, s));
+    node.compareTo?.accept(_ComparatorGenerator(resolve, s));
 
     if (node.declKind == DeclKind.interfaceKind) {
       s.write('''
@@ -504,7 +493,7 @@
       final \$d = \$i.methodDescriptor.toDartString(releaseOriginal: true);
       final \$a = \$i.args;
     ''');
-      final proxyMethodIf = _InterfaceMethodIf(resolver, s);
+      final proxyMethodIf = _InterfaceMethodIf(resolve, s);
       for (final method in node.methods) {
         method.accept(proxyMethodIf);
       }
@@ -537,7 +526,7 @@
       [
 ''');
       final interfaceAsyncMethod = _InterfaceIfAsyncMethod(
-        resolver,
+        resolve,
         s,
         implClassName: implClassName,
       );
@@ -591,7 +580,7 @@
         ...typeParams.map(
           (typeParam) => 'required $_jType<\$$typeParam> $typeParam,',
         ),
-        ...node.methods.accept(_AbstractImplFactoryArg(resolver)),
+        ...node.methods.accept(_AbstractImplFactoryArg(resolve)),
       ].join(_newLine(depth: 2)).encloseIfNotEmpty('{', '}');
       s.write('''
 abstract base mixin class $implClassName$typeParamsDef {
@@ -602,7 +591,7 @@
   $typeClassGetters
 
 ''');
-      final abstractImplMethod = _AbstractImplMethod(resolver, s);
+      final abstractImplMethod = _AbstractImplMethod(resolve, s);
       for (final method in node.methods) {
         method.accept(abstractImplMethod);
       }
@@ -612,7 +601,7 @@
       // This is for passing closures instead of implementing the class.
       final concreteCtorArgs = [
         ...typeParams.map((typeParam) => 'required this.$typeParam,'),
-        ...node.methods.accept(_ConcreteImplClosureCtorArg(resolver)),
+        ...node.methods.accept(_ConcreteImplClosureCtorArg(resolve)),
       ].join(_newLine(depth: 2)).encloseIfNotEmpty('{', '}');
       final setClosures = node.methods
           .map((method) => '_${method.finalName} = ${method.finalName}')
@@ -636,12 +625,12 @@
   $typeClassesDef
 
 ''');
-      final concreteClosureDef = _ConcreteImplClosureDef(resolver, s);
+      final concreteClosureDef = _ConcreteImplClosureDef(resolve, s);
       for (final method in node.methods) {
         method.accept(concreteClosureDef);
       }
       s.writeln();
-      final concreteMethodDef = _ConcreteImplMethod(resolver, s);
+      final concreteMethodDef = _ConcreteImplMethod(resolve, s);
       for (final method in node.methods) {
         method.accept(concreteMethodDef);
       }
@@ -654,7 +643,7 @@
       final typeClassesCall =
           typeParams.map((typeParam) => '$typeParam,').join(_newLine(depth: 2));
       final signature = node.signature;
-      final superType = superClass.accept(_TypeClassGenerator(resolver)).name;
+      final superType = superClass.accept(_TypeClassGenerator(resolve)).name;
       final hashCodeTypeClasses = typeParams.join(', ');
       final equalityTypeClasses = typeParams
           .map((typeParam) => ' &&\n        $typeParam == other.$typeParam')
@@ -678,7 +667,7 @@
                   )
                   .toList(),
             )..classDecl = node)
-              .accept(_TypeClassGenerator(resolver))
+              .accept(_TypeClassGenerator(resolve))
               .name;
       final nullable = isNullable ? '?' : '';
       s.write('''
@@ -747,7 +736,7 @@
 }
 
 /// Generates the JavaDoc comments.
-class _DocGenerator extends Visitor<JavaDocComment, void> {
+class _DocGenerator extends ElementVisitor<JavaDocComment, void> {
   final StringSink s;
   final int depth;
 
@@ -776,8 +765,8 @@
 }
 
 /// Generates the user-facing Dart type.
-class _TypeGenerator extends TypeVisitor<String> {
-  final Resolver? resolver;
+class _TypeGenerator extends TypeVisitor<String> with DefaultNonPrimitive {
+  final Resolver resolve;
 
   /// Whether the top-type of the current type being visited is nullable.
   ///
@@ -796,7 +785,7 @@
   final bool arrayType;
 
   const _TypeGenerator(
-    this.resolver, {
+    this.resolve, {
     this.forInterfaceImplementation = false,
     this.typeErasure = false,
     this.includeNullability = true,
@@ -810,7 +799,7 @@
     final nullable =
         includeNullability && node.isNullable && isTopTypeNullable ? '?' : '';
     final typeGenerator = _TypeGenerator(
-      resolver,
+      resolve,
       forInterfaceImplementation: forInterfaceImplementation,
       typeErasure: forInterfaceImplementation,
       includeNullability: true,
@@ -835,7 +824,7 @@
     final allTypeParams = node.mapTypeParameters(
       (isNullable, definedType) {
         return definedType.accept(_TypeGenerator(
-          resolver,
+          resolve,
           forInterfaceImplementation: forInterfaceImplementation,
           typeErasure: forInterfaceImplementation,
           includeNullability: true,
@@ -846,7 +835,7 @@
     );
 
     final typeParams = allTypeParams.join(', ').encloseIfNotEmpty('<', '>');
-    final prefix = resolver?.resolvePrefix(node.classDecl) ?? '';
+    final prefix = resolve(node.classDecl);
     return '$prefix${node.classDecl.finalName}$typeParams$nullable';
   }
 
@@ -884,7 +873,7 @@
       return super.visitWildcard(node);
     }
     final typeGenerator = _TypeGenerator(
-      resolver,
+      resolve,
       arrayType: arrayType,
       forInterfaceImplementation: forInterfaceImplementation,
       includeNullability:
@@ -911,7 +900,8 @@
 }
 
 /// Generates the type class.
-class _TypeClassGenerator extends TypeVisitor<_TypeClass> {
+class _TypeClassGenerator extends TypeVisitor<_TypeClass>
+    with DefaultNonPrimitive {
   final bool isConst;
 
   /// Whether the top-type of the current type being visited is nullable.
@@ -933,10 +923,10 @@
 
   final bool includeNullability;
 
-  final Resolver resolver;
+  final Resolver resolve;
 
   _TypeClassGenerator(
-    this.resolver, {
+    this.resolve, {
     this.isConst = true,
     this.boxPrimitives = false,
     this.forInterfaceImplementation = false,
@@ -949,7 +939,7 @@
   _TypeClass visitArrayType(ArrayType node) {
     final innerTypeClass = node.elementType.accept(
       _TypeClassGenerator(
-        resolver,
+        resolve,
         isConst: false,
         boxPrimitives: false,
         forInterfaceImplementation: forInterfaceImplementation,
@@ -960,7 +950,7 @@
     );
     final innerType = node.elementType.accept(
       _TypeGenerator(
-        resolver,
+        resolve,
         forInterfaceImplementation: forInterfaceImplementation,
         // Do type erasure for interface implementation.
         typeErasure: forInterfaceImplementation,
@@ -993,7 +983,7 @@
     final allTypeClasses = node.mapTypeParameters(
       (isNullable, definedType) {
         return definedType.accept(_TypeClassGenerator(
-          resolver,
+          resolve,
           isConst: false,
           boxPrimitives: false,
           forInterfaceImplementation: forInterfaceImplementation,
@@ -1024,7 +1014,7 @@
       (isNullable, definedType) {
         return definedType.accept(
           _TypeGenerator(
-            resolver,
+            resolve,
             forInterfaceImplementation: forInterfaceImplementation,
             // Do type erasure for interface implementation.
             typeErasure: forInterfaceImplementation,
@@ -1034,7 +1024,7 @@
       },
     );
     final typeArgs = typeArgsList.join(', ').encloseIfNotEmpty('<', '>');
-    final prefix = resolver.resolvePrefix(node.classDecl);
+    final prefix = resolve(node.classDecl);
     return _TypeClass('$ifConst$prefix$type$typeArgs($args)', canBeConst);
   }
 
@@ -1083,7 +1073,7 @@
       return super.visitWildcard(node);
     }
     final typeClassGenerator = _TypeClassGenerator(
-      resolver,
+      resolve,
       boxPrimitives: boxPrimitives,
       forInterfaceImplementation: forInterfaceImplementation,
       includeNullability:
@@ -1105,7 +1095,7 @@
   }
 }
 
-class _TypeParamDef extends Visitor<TypeParam, String> {
+class _TypeParamDef extends ElementVisitor<TypeParam, String> {
   const _TypeParamDef();
 
   @override
@@ -1117,10 +1107,10 @@
   }
 }
 
-class _JniResultGetter extends TypeVisitor<String> {
-  final Resolver resolver;
+class _JniResultGetter extends TypeVisitor<String> with DefaultNonPrimitive {
+  final Resolver resolve;
 
-  _JniResultGetter(this.resolver);
+  _JniResultGetter(this.resolve);
 
   @override
   String visitPrimitiveType(PrimitiveType node) {
@@ -1132,8 +1122,8 @@
 
   @override
   String visitNonPrimitiveType(ReferredType node) {
-    final typeClass = node.accept(_TypeClassGenerator(resolver)).name;
-    final type = node.accept(_TypeGenerator(resolver));
+    final typeClass = node.accept(_TypeClassGenerator(resolve)).name;
+    final type = node.accept(_TypeGenerator(resolve));
     return 'object<$type>($typeClass)';
   }
 }
@@ -1143,7 +1133,7 @@
 /// When `isFfi` is `true`, it generates the ffi type signature for vararg.
 ///
 /// For example `ffi.Int32` is an ffi type signature while `int` is a Dart one.
-class _TypeSig extends TypeVisitor<String> {
+class _TypeSig extends TypeVisitor<String> with DefaultNonPrimitive {
   final bool isFfi;
 
   const _TypeSig({required this.isFfi});
@@ -1161,7 +1151,7 @@
   }
 }
 
-class _ToNativeSuffix extends TypeVisitor<String> {
+class _ToNativeSuffix extends TypeVisitor<String> with DefaultNonPrimitive {
   const _ToNativeSuffix();
 
   @override
@@ -1178,16 +1168,16 @@
   }
 }
 
-class _FieldGenerator extends Visitor<Field, void> {
+class _FieldGenerator extends ElementVisitor<Field, void> {
   final Config config;
-  final Resolver resolver;
+  final Resolver resolve;
   final StringSink s;
   final bool isTopLevel;
   final String classRef;
 
   const _FieldGenerator(
     this.config,
-    this.resolver,
+    this.resolve,
     this.s, {
     required this.isTopLevel,
     required this.classRef,
@@ -1211,14 +1201,14 @@
   String dartOnlyGetter(Field node) {
     final name = node.finalName;
     final self = node.isStatic ? classRef : _self;
-    final type = node.type.accept(_TypeClassGenerator(resolver)).name;
+    final type = node.type.accept(_TypeClassGenerator(resolve)).name;
     return '_id_$name.get($self, $type)';
   }
 
   String dartOnlySetter(Field node) {
     final name = node.finalName;
     final self = node.isStatic ? classRef : _self;
-    final type = node.type.accept(_TypeClassGenerator(resolver)).name;
+    final type = node.type.accept(_TypeClassGenerator(resolve)).name;
     return '_id_$name.set($self, $type, value)';
   }
 
@@ -1252,7 +1242,7 @@
 
     final name = node.finalName;
     final ifStatic = node.isStatic && !isTopLevel ? 'static ' : '';
-    final type = node.type.accept(_TypeGenerator(resolver));
+    final type = node.type.accept(_TypeGenerator(resolve));
     s.write('$ifStatic$type get $name => ');
     s.write(dartOnlyGetter(node));
     s.writeln(';\n');
@@ -1267,7 +1257,7 @@
   }
 }
 
-class _MethodTypeSig extends Visitor<Method, String> {
+class _MethodTypeSig extends ElementVisitor<Method, String> {
   final bool isFfi;
 
   const _MethodTypeSig({required this.isFfi});
@@ -1293,16 +1283,16 @@
 }
 
 /// Generates Dart bindings for Java methods.
-class _MethodGenerator extends Visitor<Method, void> {
+class _MethodGenerator extends ElementVisitor<Method, void> {
   final Config config;
-  final Resolver resolver;
+  final Resolver resolve;
   final StringSink s;
   final bool isTopLevel;
   final String classRef;
 
   const _MethodGenerator(
     this.config,
-    this.resolver,
+    this.resolve,
     this.s, {
     required this.isTopLevel,
     required this.classRef,
@@ -1358,7 +1348,7 @@
       '_id_$name as $_jni.JMethodIDPtr',
       ...node.params.accept(const _ParamCall()),
     ].join(', ');
-    final resultGetter = node.returnType.accept(_JniResultGetter(resolver));
+    final resultGetter = node.returnType.accept(_JniResultGetter(resolve));
     return '_$name($params).$resultGetter';
   }
 
@@ -1385,7 +1375,7 @@
 
     // Used for inferring the type parameter from the given parameters.
     final typeLocators = node.params
-        .accept(_ParamTypeLocator(resolver: resolver))
+        .accept(_ParamTypeLocator(resolve: resolve))
         .fold(<String, List<String>>{}, _mergeMapValues).map(
       (key, value) =>
           MapEntry(key, value.delimited(', ').encloseIfNotEmpty('[', ']')),
@@ -1414,7 +1404,7 @@
       final className = node.classDecl.finalName;
       final name = node.finalName;
       final ctorName = name == 'new\$' ? className : '$className.$name';
-      final paramsDef = node.params.accept(_ParamDef(resolver)).delimited(', ');
+      final paramsDef = node.params.accept(_ParamDef(resolve)).delimited(', ');
       final typeParamsCall = node.classDecl.allTypeParams
           .map((typeParam) => '$_typeParamPrefix${typeParam.name}')
           .join(', ')
@@ -1449,10 +1439,10 @@
     final name = node.finalName;
     final returnType = isSuspendFun(node)
         ? '$_core.Future<'
-            '${node.asyncReturnType!.accept(_TypeGenerator(resolver))}>'
-        : node.returnType.accept(_TypeGenerator(resolver));
+            '${node.asyncReturnType!.accept(_TypeGenerator(resolve))}>'
+        : node.returnType.accept(_TypeGenerator(resolve));
     final ifStatic = node.isStatic && !isTopLevel ? 'static ' : '';
-    final defArgs = node.params.accept(_ParamDef(resolver)).toList();
+    final defArgs = node.params.accept(_ParamDef(resolve)).toList();
     final typeClassDef = node.typeParams
         .map(
           (typeParam) => typeParam.accept(
@@ -1474,9 +1464,9 @@
     final callExpr = methodCall(node);
     if (isSuspendFun(node)) {
       final returningType =
-          node.asyncReturnType!.accept(_TypeGenerator(resolver));
+          node.asyncReturnType!.accept(_TypeGenerator(resolve));
       final returningTypeClass =
-          node.asyncReturnType!.accept(_TypeClassGenerator(resolver)).name;
+          node.asyncReturnType!.accept(_TypeClassGenerator(resolve)).name;
       final isNullable = node.asyncReturnType!.isNullable;
       final continuation = node.params.last.finalName;
       s.write('''async {
@@ -1587,7 +1577,7 @@
 /// ```dart
 /// void bar(..., {required JObjType<T> $T}) => ...
 /// ```
-class _MethodTypeClassDef extends Visitor<TypeParam, String> {
+class _MethodTypeClassDef extends ElementVisitor<TypeParam, String> {
   final bool isRequired;
 
   const _MethodTypeClassDef({required this.isRequired});
@@ -1608,7 +1598,7 @@
 ///   Foo(..., {required this.$T}) => ...
 /// }
 /// ```
-class _CtorTypeClassDef extends Visitor<TypeParam, String> {
+class _CtorTypeClassDef extends ElementVisitor<TypeParam, String> {
   final bool isRequired;
 
   const _CtorTypeClassDef({required this.isRequired});
@@ -1626,17 +1616,17 @@
 /// ```dart
 /// void bar(Foo foo) => ...
 /// ```
-class _ParamDef extends Visitor<Param, String> {
-  final Resolver resolver;
+class _ParamDef extends ElementVisitor<Param, String> {
+  final Resolver resolve;
   final bool methodGenericErasure;
 
-  const _ParamDef(this.resolver, {this.methodGenericErasure = false});
+  const _ParamDef(this.resolve, {this.methodGenericErasure = false});
 
   @override
   String visit(Param node) {
     final type = node.type.accept(
       _TypeGenerator(
-        resolver,
+        resolve,
         forInterfaceImplementation: methodGenericErasure,
       ),
     );
@@ -1653,7 +1643,7 @@
 /// ```dart
 /// final _foo = foo.reference;
 /// ```
-class _ParamReference extends Visitor<Param, String> {
+class _ParamReference extends ElementVisitor<Param, String> {
   const _ParamReference();
 
   @override
@@ -1674,7 +1664,7 @@
 /// ```dart
 /// void bar(Foo foo) => _bar(foo.reference.pointer);
 /// ```
-class _ParamCall extends Visitor<Param, String> {
+class _ParamCall extends ElementVisitor<Param, String> {
   const _ParamCall();
 
   @override
@@ -1736,17 +1726,18 @@
 /// ((((a.$type as JArrayType).elementType) as $JMapType).V)
 ///   as JObjType<$T>
 /// ```
-class _ParamTypeLocator extends Visitor<Param, Map<String, List<String>>> {
-  final Resolver resolver;
+class _ParamTypeLocator
+    extends ElementVisitor<Param, Map<String, List<String>>> {
+  final Resolver resolve;
 
-  _ParamTypeLocator({required this.resolver});
+  _ParamTypeLocator({required this.resolve});
 
   @override
   Map<String, List<String>> visit(Param node) {
     if (node.isNullable) {
       return {};
     }
-    return node.type.accept(_TypeVarLocator(resolver: resolver)).map(
+    return node.type.accept(_TypeVarLocator(resolve: resolve)).map(
           (key, value) => MapEntry(
             key,
             value
@@ -1760,21 +1751,16 @@
 }
 
 class _TypeVarLocator extends TypeVisitor<Map<String, List<OutsideInBuffer>>> {
-  final Resolver resolver;
+  final Resolver resolve;
 
-  _TypeVarLocator({required this.resolver});
-
-  @override
-  Map<String, List<OutsideInBuffer>> visitNonPrimitiveType(ReferredType node) {
-    return {};
-  }
+  _TypeVarLocator({required this.resolve});
 
   @override
   Map<String, List<OutsideInBuffer>> visitWildcard(Wildcard node) {
     // TODO(https://github.com/dart-lang/native/issues/701): Support wildcards.
     if (node.superBound != null || node.extendsBound == null) {
       // Dart does not support `* super T` wildcards. Fall back to Object?.
-      return super.visitWildcard(node);
+      return {};
     }
     return node.extendsBound!.accept(this);
   }
@@ -1790,11 +1776,11 @@
   Map<String, List<OutsideInBuffer>> visitDeclaredType(DeclaredType node) {
     if (node.classDecl.isObject) {
       // The class is not generated, fall back to `JObject`.
-      return super.visitDeclaredType(node);
+      return {};
     }
     final offset = node.classDecl.allTypeParams.length - node.params.length;
     final result = <String, List<OutsideInBuffer>>{};
-    final prefix = resolver.resolvePrefix(node.classDecl);
+    final prefix = resolve(node.classDecl);
     final typeClass = '$prefix${node.classDecl.typeClassName}';
     final typeClassParams = List.filled(
       node.classDecl.allTypeParams.length,
@@ -1831,20 +1817,20 @@
 }
 
 /// Method defintion for Impl abstract class used for interface implementation.
-class _AbstractImplMethod extends Visitor<Method, void> {
-  final Resolver resolver;
+class _AbstractImplMethod extends ElementVisitor<Method, void> {
+  final Resolver resolve;
   final StringSink s;
 
-  _AbstractImplMethod(this.resolver, this.s);
+  _AbstractImplMethod(this.resolve, this.s);
 
   @override
   void visit(Method node) {
     final returnType = node.returnType.accept(
-      _TypeGenerator(resolver, forInterfaceImplementation: true),
+      _TypeGenerator(resolve, forInterfaceImplementation: true),
     );
     final name = node.finalName;
     final args = node.params
-        .accept(_ParamDef(resolver, methodGenericErasure: true))
+        .accept(_ParamDef(resolve, methodGenericErasure: true))
         .join(', ');
     s.writeln('  $returnType $name($args);');
     if (returnType == 'void') {
@@ -1854,20 +1840,20 @@
 }
 
 /// Closure defintion for concrete Impl class used for interface implementation.
-class _ConcreteImplClosureDef extends Visitor<Method, void> {
-  final Resolver resolver;
+class _ConcreteImplClosureDef extends ElementVisitor<Method, void> {
+  final Resolver resolve;
   final StringSink s;
 
-  _ConcreteImplClosureDef(this.resolver, this.s);
+  _ConcreteImplClosureDef(this.resolve, this.s);
 
   @override
   void visit(Method node) {
     final returnType = node.returnType.accept(
-      _TypeGenerator(resolver, forInterfaceImplementation: true),
+      _TypeGenerator(resolve, forInterfaceImplementation: true),
     );
     final name = node.finalName;
     final args = node.params
-        .accept(_ParamDef(resolver, methodGenericErasure: true))
+        .accept(_ParamDef(resolve, methodGenericErasure: true))
         .join(', ');
     s.writeln('  final $returnType Function($args) _$name;');
     if (returnType == 'void') {
@@ -1878,19 +1864,19 @@
 
 /// Closure argument for the factory of the implementation's abstract class.
 /// Used for interface implementation.
-class _AbstractImplFactoryArg extends Visitor<Method, String> {
-  final Resolver resolver;
+class _AbstractImplFactoryArg extends ElementVisitor<Method, String> {
+  final Resolver resolve;
 
-  _AbstractImplFactoryArg(this.resolver);
+  _AbstractImplFactoryArg(this.resolve);
 
   @override
   String visit(Method node) {
     final returnType = node.returnType.accept(
-      _TypeGenerator(resolver, forInterfaceImplementation: true),
+      _TypeGenerator(resolve, forInterfaceImplementation: true),
     );
     final name = node.finalName;
     final args = node.params
-        .accept(_ParamDef(resolver, methodGenericErasure: true))
+        .accept(_ParamDef(resolve, methodGenericErasure: true))
         .join(', ');
     final functionArg = 'required $returnType Function($args) $name,';
     if (node.returnType.name == 'void') {
@@ -1902,19 +1888,19 @@
 
 /// Closure argument for concrete Impl class constructor.
 /// Used for interface implementation.
-class _ConcreteImplClosureCtorArg extends Visitor<Method, String> {
-  final Resolver resolver;
+class _ConcreteImplClosureCtorArg extends ElementVisitor<Method, String> {
+  final Resolver resolve;
 
-  _ConcreteImplClosureCtorArg(this.resolver);
+  _ConcreteImplClosureCtorArg(this.resolve);
 
   @override
   String visit(Method node) {
     final returnType = node.returnType.accept(
-      _TypeGenerator(resolver, forInterfaceImplementation: true),
+      _TypeGenerator(resolve, forInterfaceImplementation: true),
     );
     final name = node.finalName;
     final args = node.params
-        .accept(_ParamDef(resolver, methodGenericErasure: true))
+        .accept(_ParamDef(resolve, methodGenericErasure: true))
         .join(', ');
     final functionArg = 'required $returnType Function($args) $name,';
     if (node.returnType.name == 'void') {
@@ -1925,20 +1911,20 @@
 }
 
 /// Method defintion for concrete Impl class used for interface implementation.
-class _ConcreteImplMethod extends Visitor<Method, void> {
-  final Resolver resolver;
+class _ConcreteImplMethod extends ElementVisitor<Method, void> {
+  final Resolver resolve;
   final StringSink s;
 
-  _ConcreteImplMethod(this.resolver, this.s);
+  _ConcreteImplMethod(this.resolve, this.s);
 
   @override
   void visit(Method node) {
     final returnType = node.returnType.accept(
-      _TypeGenerator(resolver, forInterfaceImplementation: true),
+      _TypeGenerator(resolve, forInterfaceImplementation: true),
     );
     final name = node.finalName;
     final argsDef = node.params
-        .accept(_ParamDef(resolver, methodGenericErasure: true))
+        .accept(_ParamDef(resolve, methodGenericErasure: true))
         .join(', ');
     final argsCall = node.params.map((param) => param.finalName).join(', ');
     s.write('''
@@ -1949,24 +1935,24 @@
 }
 
 /// The if statement to check which method has been called from the proxy class.
-class _InterfaceMethodIf extends Visitor<Method, void> {
-  final Resolver resolver;
+class _InterfaceMethodIf extends ElementVisitor<Method, void> {
+  final Resolver resolve;
   final StringSink s;
 
-  _InterfaceMethodIf(this.resolver, this.s);
+  _InterfaceMethodIf(this.resolve, this.s);
 
   @override
   void visit(Method node) {
     final isVoid = node.returnType.name == 'void';
-    final signature = node.javaSig;
+    final identifier = node.javaSig;
     final saveResult = isVoid ? '' : 'final \$r = ';
     final name = node.finalName;
     s.write('''
-        if (\$d == r'$signature') {
+        if (\$d == r'$identifier') {
           ${saveResult}_\$impls[\$p]!.$name(
 ''');
     for (var i = 0; i < node.params.length; ++i) {
-      node.params[i].accept(_InterfaceParamCast(resolver, s, paramIndex: i));
+      node.params[i].accept(_InterfaceParamCast(resolve, s, paramIndex: i));
     }
     const returnBox = _InterfaceReturnBox();
     s.write('''
@@ -1978,12 +1964,12 @@
 }
 
 /// The if statement within the async methods list to conditionally add methods.
-class _InterfaceIfAsyncMethod extends Visitor<Method, void> {
-  final Resolver resolver;
+class _InterfaceIfAsyncMethod extends ElementVisitor<Method, void> {
+  final Resolver resolve;
   final StringSink s;
   final String implClassName;
 
-  _InterfaceIfAsyncMethod(this.resolver, this.s, {required this.implClassName});
+  _InterfaceIfAsyncMethod(this.resolve, this.s, {required this.implClassName});
 
   @override
   void visit(Method node) {
@@ -2000,19 +1986,19 @@
 
 /// Generates casting to the correct parameter type from the list of JObject
 /// arguments received from the call to the proxy class.
-class _InterfaceParamCast extends Visitor<Param, void> {
-  final Resolver resolver;
+class _InterfaceParamCast extends ElementVisitor<Param, void> {
+  final Resolver resolve;
   final StringSink s;
   final int paramIndex;
 
-  _InterfaceParamCast(this.resolver, this.s, {required this.paramIndex});
+  _InterfaceParamCast(this.resolve, this.s, {required this.paramIndex});
 
   @override
   void visit(Param node) {
     final typeClass = node.type
         .accept(
           _TypeClassGenerator(
-            resolver,
+            resolve,
             boxPrimitives: true,
             forInterfaceImplementation: true,
             includeNullability: false,
@@ -2043,7 +2029,7 @@
 ///
 /// For example `$r.toJInteger().reference.toPointer()` when the return
 /// type is `integer`.
-class _InterfaceReturnBox extends TypeVisitor<String> {
+class _InterfaceReturnBox extends TypeVisitor<String> with DefaultNonPrimitive {
   const _InterfaceReturnBox();
 
   @override
@@ -2064,7 +2050,7 @@
   }
 }
 
-class _CallMethodName extends Visitor<Method, String> {
+class _CallMethodName extends ElementVisitor<Method, String> {
   const _CallMethodName();
 
   @override
@@ -2082,19 +2068,19 @@
   }
 }
 
-class _OperatorGenerator extends Visitor<Method, void> {
-  final Resolver resolver;
+class _OperatorGenerator extends ElementVisitor<Method, void> {
+  final Resolver resolve;
   final StringSink s;
   final Operator operator;
 
-  _OperatorGenerator(this.resolver, this.s, {required this.operator});
+  _OperatorGenerator(this.resolve, this.s, {required this.operator});
 
   @override
   void visit(Method node) {
     final returnType = operator.returnsVoid
         ? 'void'
-        : node.returnType.accept(_TypeGenerator(resolver));
-    final paramsDef = node.params.accept(_ParamDef(resolver)).join(', ');
+        : node.returnType.accept(_TypeGenerator(resolve));
+    final paramsDef = node.params.accept(_ParamDef(resolve)).join(', ');
     final paramsCall = node.params.map((param) => param.finalName).join(', ');
     s.write('''
   $returnType operator ${operator.dartSymbol}($paramsDef) {
@@ -2104,15 +2090,15 @@
   }
 }
 
-class _ComparatorGenerator extends Visitor<Method, void> {
-  final Resolver resolver;
+class _ComparatorGenerator extends ElementVisitor<Method, void> {
+  final Resolver resolve;
   final StringSink s;
 
-  _ComparatorGenerator(this.resolver, this.s);
+  _ComparatorGenerator(this.resolve, this.s);
 
   @override
   void visit(Method node) {
-    final paramsDef = node.params.accept(_ParamDef(resolver)).join(', ');
+    final paramsDef = node.params.accept(_ParamDef(resolve)).join(', ');
     final paramsCall = node.params.map((param) => param.finalName).join(', ');
     final name = node.finalName;
     s.write('''
diff --git a/pkgs/jnigen/lib/src/bindings/excluder.dart b/pkgs/jnigen/lib/src/bindings/excluder.dart
deleted file mode 100644
index fb4624a..0000000
--- a/pkgs/jnigen/lib/src/bindings/excluder.dart
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import '../config/config.dart';
-import '../elements/elements.dart';
-import '../logging/logging.dart';
-import 'visitor.dart';
-
-extension on ClassMember {
-  bool get isPrivate => !isPublic;
-}
-
-// TODO(https://github.com/dart-lang/native/issues/1164): Kotlin compiler
-// appends the method name with a dash and a hash code when arguments contain
-// inline classes. This is because inline classes do not have any runtime type
-// and the typical operator overloading supported by JVM cannot work for them.
-//
-// Once we support inline classes, we can relax the following constraints.
-final _validDartIdentifier = RegExp(r'^[a-zA-Z_$][a-zA-Z0-9_$]*$');
-
-extension on String {
-  bool get isInvalidDartIdentifier =>
-      !_validDartIdentifier.hasMatch(this) &&
-      this != '<init>' &&
-      this != '<clinit>';
-}
-
-class Excluder extends Visitor<Classes, void> with TopLevelVisitor {
-  @override
-  final GenerationStage stage = GenerationStage.excluder;
-
-  final Config config;
-
-  const Excluder(this.config);
-
-  @override
-  void visit(Classes node) {
-    node.decls.removeWhere((_, classDecl) {
-      final excluded = classDecl.isPrivate || classDecl.isExcluded;
-      if (excluded) {
-        log.fine('Excluded class ${classDecl.binaryName}');
-      }
-      if (classDecl.name.isInvalidDartIdentifier) {
-        log.warning('Excluded class ${classDecl.binaryName}: the name is not a'
-            ' valid Dart identifer');
-        return true;
-      }
-      return excluded;
-    });
-    final classExcluder = _ClassExcluder(config);
-    for (final classDecl in node.decls.values) {
-      classDecl.accept(classExcluder);
-    }
-  }
-}
-
-class _ClassExcluder extends Visitor<ClassDecl, void> {
-  final Config config;
-
-  _ClassExcluder(this.config);
-
-  @override
-  void visit(ClassDecl node) {
-    node.methods = node.methods.where((method) {
-      final isExcluded = method.userDefinedIsExcluded;
-      final isPrivate = method.isPrivate;
-      final isAbstractCtor = method.isConstructor && node.isAbstract;
-      final isBridgeMethod = method.isSynthetic && method.isBridge;
-      final excluded =
-          isPrivate || isAbstractCtor || isBridgeMethod || isExcluded;
-      if (excluded) {
-        log.fine('Excluded method ${node.binaryName}#${method.name}');
-      }
-      if (method.name.isInvalidDartIdentifier) {
-        log.warning(
-            'Excluded method ${node.binaryName}#${method.name}: the name is not'
-            ' a valid Dart identifer');
-        return false;
-      }
-      return !excluded;
-    }).toList();
-    node.fields = node.fields.where((field) {
-      final excluded = field.isExcluded || field.isPrivate;
-      if (excluded) {
-        log.fine('Excluded field ${node.binaryName}#${field.name}');
-      }
-      if (field.name.isInvalidDartIdentifier) {
-        log.warning(
-            'Excluded field ${node.binaryName}#${field.name}: the name is not'
-            ' a valid Dart identifer');
-        return false;
-      }
-      return !excluded;
-    }).toList();
-  }
-}
diff --git a/pkgs/jnigen/lib/src/bindings/exporter.dart b/pkgs/jnigen/lib/src/bindings/exporter.dart
new file mode 100644
index 0000000..abd192e
--- /dev/null
+++ b/pkgs/jnigen/lib/src/bindings/exporter.dart
@@ -0,0 +1,209 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:pub_semver/pub_semver.dart';
+
+import '../config/config.dart';
+import '../elements/elements.dart';
+import '../elements/stability_models.dart';
+import '../logging/logging.dart';
+import 'visitor.dart';
+
+final _version = Version(1, 0, 0);
+
+extension<T extends Element<T>> on Iterable<T> {
+  Map<String, E> acceptAndMap<E>(ElementVisitor<T, E> visitor,
+      {required String Function(T) key}) {
+    final map = <String, E>{};
+    for (final element in this) {
+      map[key(element)] = element.accept(visitor);
+    }
+    return map;
+  }
+}
+
+/// Generates the JSON used for API stability and importing.
+class Exporter extends ElementVisitor<Classes, Future<void>>
+    with TopLevelVisitor {
+  @override
+  final stage = GenerationStage.exporter;
+
+  final Config config;
+
+  Exporter(this.config);
+
+  @override
+  Future<void> visit(Classes node) async {
+    final exportFileUri = config.outputConfig.symbolsConfig?.path ??
+        Uri.file('jnigen_symbols.json');
+
+    // FIXME: add package name
+    final apiStabilityInfo = StabilityInfo(
+      formatVersion: _version,
+      packageName: 'tbd',
+      files: node.files.values
+          .acceptAndMap(_fileExporter, key: (file) => file.path),
+    );
+
+    final exportFile = File.fromUri(exportFileUri);
+    final sink = exportFile.openWrite();
+    await sink.addStream(
+        Stream.value(apiStabilityInfo).transform(JsonUtf8Encoder('  ').cast()));
+    await sink.close();
+  }
+}
+
+const _fileExporter = _FileExporter();
+
+class _FileExporter extends ElementVisitor<DartFile, StabilityFile> {
+  const _FileExporter();
+
+  @override
+  StabilityFile visit(DartFile node) {
+    return StabilityFile(
+      classes: node.classes.values
+          .acceptAndMap(_classExporter, key: (cls) => cls.binaryName),
+    );
+  }
+}
+
+const _classExporter = _ClassExporter();
+
+class _ClassExporter extends ElementVisitor<ClassDecl, StabilityClass> {
+  const _ClassExporter();
+
+  @override
+  StabilityClass visit(ClassDecl node) {
+    return StabilityClass(
+      name: node.finalName!,
+      superClass: node.superclass!.accept(_typeExporter),
+      superInterfaces: node.interfaces.accept(_typeExporter).toList(),
+      fields:
+          node.fields.acceptAndMap(_fieldExporter, key: (field) => field.name),
+      methods: node.methods
+          .acceptAndMap(_methodExporter, key: (method) => method.javaSig),
+      typeParameters: node.allTypeParams.accept(_typeParamExporter).toList(),
+    );
+  }
+}
+
+const _fieldExporter = _FieldExporter();
+
+class _FieldExporter extends ElementVisitor<Field, StabilityField> {
+  const _FieldExporter();
+
+  @override
+  StabilityField visit(Field node) {
+    return StabilityField(
+      name: node.finalName!,
+      type: node.type.accept(_typeExporter),
+    );
+  }
+}
+
+const _methodExporter = _MethodExporter();
+
+class _MethodExporter extends ElementVisitor<Method, StabilityMethod> {
+  const _MethodExporter();
+
+  @override
+  StabilityMethod visit(Method node) {
+    if (node.finalName == null) {
+      log.warning(
+          '${node.classDecl.binaryName}#${node.javaSig} has a null finalName');
+    }
+    return StabilityMethod(
+      name: node.finalName ?? 'NULL',
+      typeParameters: node.typeParams.accept(_typeParamExporter).toList(),
+      methodParameters: node.params.accept(_paramExporter).toList(),
+      returnType: node.returnType.accept(_typeExporter),
+    );
+  }
+}
+
+const _paramExporter = _ParamExporter();
+
+class _ParamExporter extends ElementVisitor<Param, StabilityMethodParameter> {
+  const _ParamExporter();
+
+  @override
+  StabilityMethodParameter visit(Param node) {
+    return StabilityMethodParameter(
+      name: node.finalName!,
+      type: node.type.accept(_typeExporter),
+    );
+  }
+}
+
+const _typeParamExporter = _TypeParamExporter();
+
+class _TypeParamExporter
+    extends ElementVisitor<TypeParam, StabilityTypeParameter> {
+  const _TypeParamExporter();
+
+  @override
+  StabilityTypeParameter visit(TypeParam node) {
+    return StabilityTypeParameter(
+      name: node.name,
+      bounds: node.bounds.accept(_typeExporter).toList(),
+    );
+  }
+}
+
+const _typeExporter = _TypeExporter();
+
+class _TypeExporter extends TypeVisitor<StabilityType> {
+  const _TypeExporter();
+
+  Nullability nullabilityFromType(ReferredType type) {
+    // TODO(https://github.com/dart-lang/native/issues/2356): Also refactor this
+    // in the internal representation.
+    if (type.hasNullable) return Nullability.nullable;
+    if (type.hasNonNull) return Nullability.nonNullable;
+    return Nullability.platform;
+  }
+
+  @override
+  StabilityType visitArrayType(ArrayType node) {
+    return StabilityArrayType(
+      elementType: node.elementType.accept(_typeExporter),
+      nullability: nullabilityFromType(node),
+    );
+  }
+
+  @override
+  StabilityType visitPrimitiveType(PrimitiveType node) {
+    return StabilityPrimitiveType(name: node.name);
+  }
+
+  @override
+  StabilityType visitDeclaredType(DeclaredType node) {
+    return StabilityDeclaredType(
+      binaryName: node.binaryName,
+      typeArguments:
+          node.params.map((param) => param.accept(_typeExporter)).toList(),
+      nullability: nullabilityFromType(node),
+    );
+  }
+
+  @override
+  StabilityType visitTypeVar(TypeVar node) {
+    return StabilityTypeVariable(
+      name: node.name,
+      nullability: nullabilityFromType(node),
+    );
+  }
+
+  @override
+  StabilityType visitWildcard(Wildcard node) {
+    return StabilityWildcard(
+      extendsBound: node.extendsBound?.accept(_typeExporter),
+      superBound: node.superBound?.accept(_typeExporter),
+      nullability: nullabilityFromType(node),
+    );
+  }
+}
diff --git a/pkgs/jnigen/lib/src/bindings/graph_builder.dart b/pkgs/jnigen/lib/src/bindings/graph_builder.dart
new file mode 100644
index 0000000..d24398d
--- /dev/null
+++ b/pkgs/jnigen/lib/src/bindings/graph_builder.dart
@@ -0,0 +1,110 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection';
+
+import 'package:path/path.dart' as p;
+
+import '../config/config.dart';
+import '../elements/elements.dart';
+import '../transformers/graph.dart' as graph;
+import 'visitor.dart';
+
+/// This creates the user-facing graph used for transformations like renaming,
+/// excluding, and adding extra methods.
+class GraphBuilder extends ElementVisitor<Classes, graph.Bindings>
+    with TopLevelVisitor {
+  @override
+  final stage = GenerationStage.graphBuilder;
+
+  final Config config;
+
+  GraphBuilder(this.config);
+
+  @override
+  graph.Bindings visit(Classes node) {
+    final classes = <String, graph.Class>{};
+    final visiting = <String>{};
+    final classNodeBuilder = _ClassNodeBuilder(classes, visiting);
+    for (final classDecl in node.decls.values) {
+      if (!classes.containsKey(classDecl.binaryName)) {
+        classDecl.accept(classNodeBuilder);
+      }
+    }
+    final files = LinkedHashMap<String, graph.DartFile>(
+        equals: p.equals, hashCode: p.hash);
+    final fileNodeBuilder = _FileNodeBuilder(classes);
+    for (final MapEntry(key: path, value: file) in node.files.entries) {
+      files[path] = file.accept(fileNodeBuilder);
+    }
+    return graph.Bindings(node, classes, files);
+  }
+}
+
+class _ClassNodeBuilder extends ElementVisitor<ClassDecl, void> {
+  final Map<String, graph.Class> classes;
+  final Set<String> visiting;
+
+  _ClassNodeBuilder(this.classes, this.visiting);
+
+  @override
+  void visit(ClassDecl node) {
+    // First visit the outer-class, the superclass, and the super-interfaces of
+    // this class to maintain topological ordering.
+    if (classes.containsKey(node.binaryName) ||
+        visiting.contains(node.binaryName)) {
+      return;
+    }
+    visiting.add(node.binaryName);
+    node.outerClass?.accept(this);
+    if (node.superclass case final DeclaredType superType) {
+      if (!superType.classDecl.isImported) {
+        superType.classDecl.accept(this);
+      }
+    }
+    for (final interface in node.interfaces) {
+      if (interface case final DeclaredType superInterface) {
+        if (!superInterface.classDecl.isImported) {
+          superInterface.classDecl.accept(this);
+        }
+      }
+    }
+    final properties = Map.fromEntries(node.fields
+        .map((field) => MapEntry(field.name, graph.Property(field))));
+    final methods = <String, graph.Method>{};
+    final methodNodeBuilder = _MethodNodeBuilder();
+    for (final method in node.methods) {
+      methods[method.javaSig] = method.accept(methodNodeBuilder);
+    }
+    classes[node.binaryName] = graph.Class(node, properties, methods)
+      ..enclosingClass = node.outerClassBinaryName == null
+          ? null
+          : classes[node.outerClassBinaryName!];
+    visiting.remove(node.binaryName);
+  }
+}
+
+class _FileNodeBuilder extends ElementVisitor<DartFile, graph.DartFile> {
+  final Map<String, graph.Class> allClasses;
+
+  _FileNodeBuilder(this.allClasses);
+
+  @override
+  graph.DartFile visit(DartFile node) {
+    final classes = <String, graph.Class>{};
+    for (final binaryName in node.classes.keys) {
+      classes[binaryName] = allClasses[binaryName]!;
+    }
+    return graph.DartFile(node, classes);
+  }
+}
+
+class _MethodNodeBuilder extends ElementVisitor<Method, graph.Method> {
+  @override
+  graph.Method visit(Method node) {
+    final parameters = UnmodifiableListView(
+        node.params.map(graph.MethodParameter.new).toList());
+    return graph.Method(node, parameters);
+  }
+}
diff --git a/pkgs/jnigen/lib/src/bindings/importer.dart b/pkgs/jnigen/lib/src/bindings/importer.dart
new file mode 100644
index 0000000..b894247
--- /dev/null
+++ b/pkgs/jnigen/lib/src/bindings/importer.dart
@@ -0,0 +1,141 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:pub_semver/pub_semver.dart';
+import 'package:yaml/yaml.dart';
+
+import '../config/config_types.dart';
+import '../elements/elements.dart';
+import '../logging/logging.dart';
+import '../util/find_package.dart';
+import 'visitor.dart';
+
+/// Modify this when symbols file format changes according to pub_semver.
+final jsonVersion = Version(1, 0, 0);
+
+/// Imports the stability information from the previous runs of JNIgen from this
+/// and other packages.
+class Importer extends ElementVisitor<Classes, Future<void>>
+    with TopLevelVisitor {
+  @override
+  final stage = GenerationStage.importer;
+
+  final Config config;
+
+  Importer(this.config);
+
+  @override
+  Future<void> visit(Classes node) async {
+    for (final import in [
+      // Implicitly importing package:jni symbols.
+      Uri.parse('package:jni/jni_symbols.yaml'),
+      ...?config.imports,
+    ]) {
+      // Getting the actual uri in case of package uris.
+      final Uri yamlUri;
+      final String importPath;
+      if (import.scheme == 'package') {
+        final packageName = import.pathSegments.first;
+        final packageRoot = await findPackageRoot(packageName);
+        if (packageRoot == null) {
+          log.fatal('package:$packageName was not found.');
+        }
+        yamlUri = packageRoot
+            .resolve('lib/')
+            .resolve(import.pathSegments.sublist(1).join('/'));
+        importPath = 'package:$packageName';
+      } else {
+        yamlUri = import;
+        importPath = ([...import.pathSegments]..removeLast()).join('/');
+      }
+      log.finest('Parsing yaml file in url $yamlUri.');
+      final YamlMap yaml;
+      try {
+        final symbolsFile = File.fromUri(yamlUri);
+        final content = symbolsFile.readAsStringSync();
+        yaml = loadYaml(content, sourceUrl: yamlUri) as YamlMap;
+      } catch (e, s) {
+        log.warning(e);
+        log.warning(s);
+        log.fatal('Error while parsing yaml file "$import".');
+      }
+      final version = Version.parse(yaml['version'] as String);
+      if (!VersionConstraint.compatibleWith(jsonVersion).allows(version)) {
+        log.fatal('"$import" is version "$version" which is not compatible with'
+            'the current JNIgen symbols version $jsonVersion');
+      }
+      final files = yaml['files'] as YamlMap;
+      for (final entry in files.entries) {
+        final filePath = entry.key as String;
+        final dartFile = DartFile('$importPath/$filePath', {});
+        final classes = entry.value as YamlMap;
+        for (final classEntry in classes.entries) {
+          final binaryName = classEntry.key as String;
+          final decl = classEntry.value as YamlMap;
+          if (node.importedClasses.containsKey(binaryName)) {
+            log.fatal(
+              'Re-importing "$binaryName" in "$import".\n'
+              'Try hiding the class in import.',
+            );
+          }
+          final classDecl = ClassDecl(
+            declKind: DeclKind.classKind,
+            binaryName: binaryName,
+          )
+            ..isImported = true
+            ..file = dartFile
+            ..finalName = decl['name'] as String
+            ..superCount = decl['super_count'] as int
+            ..allTypeParams = []
+            // TODO(https://github.com/dart-lang/native/issues/746): include
+            // outerClass in the interop information.
+            ..outerClass = null;
+          for (final typeParamEntry
+              in (decl['type_params'] as YamlMap?)?.entries ??
+                  <MapEntry<dynamic, dynamic>>[]) {
+            final typeParamName = typeParamEntry.key as String;
+            final bounds = (typeParamEntry.value as YamlMap).entries.map((e) {
+              final boundName = e.key as String;
+              // Can only be DECLARED or TYPE_VARIABLE
+              if (!['DECLARED', 'TYPE_VARIABLE'].contains(e.value)) {
+                log.fatal(
+                  'Unsupported bound kind "${e.value}" for bound "$boundName" '
+                  'in type parameter "$typeParamName" '
+                  'of "$binaryName".',
+                );
+              }
+              final ReferredType type;
+              if ((e.value as String) == 'DECLARED') {
+                type = DeclaredType(binaryName: boundName);
+              } else {
+                type = TypeVar(name: boundName);
+              }
+              return type;
+            }).toList();
+            classDecl.allTypeParams.add(
+              TypeParam(name: typeParamName, bounds: bounds),
+            );
+          }
+          node.importedClasses[binaryName] = classDecl;
+        }
+      }
+
+      if (node.importedClasses.keys
+          .toSet()
+          .intersection(node.decls.keys.toSet())
+          .isNotEmpty) {
+        log.fatal(
+          'Trying to re-import the generated classes.\n'
+          'Try hiding the class(es) in import.',
+        );
+      }
+
+      for (final className in node.importedClasses.keys) {
+        log.finest('Imported $className successfully.');
+      }
+    }
+  }
+}
diff --git a/pkgs/jnigen/lib/src/bindings/kotlin_processor.dart b/pkgs/jnigen/lib/src/bindings/kotlin_processor.dart
index 0b315de..a23b922 100644
--- a/pkgs/jnigen/lib/src/bindings/kotlin_processor.dart
+++ b/pkgs/jnigen/lib/src/bindings/kotlin_processor.dart
@@ -30,9 +30,10 @@
       binaryName;
 }
 
-/// A [Visitor] that adds the the information from Kotlin's metadata to the Java
-/// classes and methods.
-class KotlinProcessor extends Visitor<Classes, void> with TopLevelVisitor {
+/// An [ElementVisitor] that adds the the information from Kotlin's metadata to
+/// the Java classes and methods.
+class KotlinProcessor extends ElementVisitor<Classes, void>
+    with TopLevelVisitor {
   @override
   final GenerationStage stage = GenerationStage.kotlinProcessor;
 
@@ -45,20 +46,21 @@
   }
 }
 
-class _KotlinClassProcessor extends Visitor<ClassDecl, void> {
+class _KotlinClassProcessor extends ElementVisitor<ClassDecl, void> {
   @override
   void visit(ClassDecl node) {
     if (node.kotlinClass == null && node.kotlinPackage == null) {
       return;
     }
     // This [ClassDecl] is actually a Kotlin class.
-    if (node.kotlinClass != null) {
-      for (var i = 0; i < node.kotlinClass!.typeParameters.length; ++i) {
-        node.typeParams[i].accept(
-            _KotlinTypeParamProcessor(node.kotlinClass!.typeParameters[i]));
+    if (node.kotlinClass case final kotlinClass?) {
+      node.originalName = kotlinClass.name;
+      for (var i = 0; i < kotlinClass.typeParameters.length; ++i) {
+        node.typeParams[i]
+            .accept(_KotlinTypeParamProcessor(kotlinClass.typeParameters[i]));
       }
       if (node.superclass case final superClass?) {
-        final kotlinSuperTypes = node.kotlinClass!.superTypes.where(
+        final kotlinSuperTypes = kotlinClass.superTypes.where(
           (superType) =>
               _toJavaBinaryName(superType.name ?? '') == superClass.name,
         );
@@ -131,13 +133,14 @@
   }
 }
 
-class _KotlinMethodProcessor extends Visitor<Method, void> {
+class _KotlinMethodProcessor extends ElementVisitor<Method, void> {
   final KotlinFunction function;
 
   _KotlinMethodProcessor(this.function);
 
   @override
   void visit(Method node) {
+    node.originalName = function.name;
     _processParams(node.params, function.valueParameters);
     node.kotlinFunction = function;
     for (var i = 0; i < node.typeParams.length; ++i) {
@@ -171,7 +174,7 @@
   }
 }
 
-class _KotlinConstructorProcessor extends Visitor<Method, void> {
+class _KotlinConstructorProcessor extends ElementVisitor<Method, void> {
   final KotlinConstructor constructor;
 
   _KotlinConstructorProcessor(this.constructor);
@@ -182,7 +185,7 @@
   }
 }
 
-class _KotlinGetterProcessor extends Visitor<Method, void> {
+class _KotlinGetterProcessor extends ElementVisitor<Method, void> {
   final KotlinProperty getter;
 
   _KotlinGetterProcessor(this.getter);
@@ -193,7 +196,7 @@
   }
 }
 
-class _KotlinSetterProcessor extends Visitor<Method, void> {
+class _KotlinSetterProcessor extends ElementVisitor<Method, void> {
   final KotlinProperty setter;
 
   _KotlinSetterProcessor(this.setter);
@@ -207,29 +210,31 @@
   }
 }
 
-class _KotlinPropertyProcessor extends Visitor<Field, void> {
+class _KotlinPropertyProcessor extends ElementVisitor<Field, void> {
   final KotlinProperty property;
 
   _KotlinPropertyProcessor(this.property);
 
   @override
   void visit(Field node) {
+    node.originalName = property.kotlinName;
     node.type.accept(_KotlinTypeProcessor(property.returnType));
   }
 }
 
-class _KotlinParamProcessor extends Visitor<Param, void> {
+class _KotlinParamProcessor extends ElementVisitor<Param, void> {
   final KotlinValueParameter kotlinParam;
 
   _KotlinParamProcessor(this.kotlinParam);
 
   @override
   void visit(Param node) {
+    node.originalName = kotlinParam.name;
     node.type.accept(_KotlinTypeProcessor(kotlinParam.type));
   }
 }
 
-class _KotlinTypeParamProcessor extends Visitor<TypeParam, void> {
+class _KotlinTypeParamProcessor extends ElementVisitor<TypeParam, void> {
   final KotlinTypeParameter kotlinTypeParam;
 
   _KotlinTypeParamProcessor(this.kotlinTypeParam);
@@ -251,7 +256,7 @@
   }
 }
 
-class _KotlinTypeProcessor extends TypeVisitor<void> {
+class _KotlinTypeProcessor extends TypeVisitor<void> with DefaultNonPrimitive {
   final KotlinType kotlinType;
 
   _KotlinTypeProcessor(this.kotlinType);
diff --git a/pkgs/jnigen/lib/src/bindings/linker.dart b/pkgs/jnigen/lib/src/bindings/linker.dart
index 512ee46..eda6fb1 100644
--- a/pkgs/jnigen/lib/src/bindings/linker.dart
+++ b/pkgs/jnigen/lib/src/bindings/linker.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:io';
+
 import '../config/config.dart';
 import '../elements/elements.dart';
 import '../logging/logging.dart';
@@ -9,14 +11,15 @@
 
 typedef _Resolver = ClassDecl Function(String? binaryName);
 
-/// A [Visitor] that adds the correct [ClassDecl] references from the
+/// An [ElementVisitor] that adds the correct [ClassDecl] references from the
 /// string binary names.
 ///
 /// It adds the following references:
 /// * Links [ClassDecl] objects from imported dependencies.
 /// * Adds references from child elements back to their parent elements.
 /// * Resolves Kotlin specific `asyncReturnType` for methods.
-class Linker extends Visitor<Classes, Future<void>> with TopLevelVisitor {
+class Linker extends ElementVisitor<Classes, Future<void>>
+    with TopLevelVisitor {
   @override
   final GenerationStage stage = GenerationStage.linker;
 
@@ -32,8 +35,9 @@
         OutputStructure.singleFile) {
       // Connect all to the root if the output is in single file mode.
       final path = root.toFilePath();
+      final file = node.files[path] ??= DartFile(path, {...node.decls});
       for (final decl in node.decls.values) {
-        decl.path = path;
+        decl.file = file;
       }
     } else {
       for (final decl in node.decls.values) {
@@ -41,61 +45,52 @@
         final className = dollarSign != -1
             ? decl.binaryName.substring(0, dollarSign)
             : decl.binaryName;
-        final path = className.replaceAll('.', '/');
-        decl.path = root.resolve(path).toFilePath();
+        final path = root
+            .resolve(
+              '${className.replaceAll('.', Platform.pathSeparator)}.dart',
+            )
+            .toFilePath();
+        final file = node.files[path] ??= DartFile(path, {});
+        decl.file = file;
+        file.classes[decl.binaryName] = decl;
+        // Create a `_package.dart` file in each package that exports all of the
+        // classes within that package.
+        final packagePath = root
+            .resolve(decl.packageName.replaceAll('.', Platform.pathSeparator))
+            .resolve('_package.dart')
+            .toFilePath();
+        final packageFile = node.files[packagePath] ??= DartFile(
+          packagePath,
+          {},
+        );
+        packageFile.exports.add(file);
       }
     }
 
-    // Find all the imported classes.
-    await config.importClasses();
-
-    if (config.importedClasses.keys
-        .toSet()
-        .intersection(node.decls.keys.toSet())
-        .isNotEmpty) {
-      log.fatal(
-        'Trying to re-import the generated classes.\n'
-        'Try hiding the class(es) in import.',
-      );
-    }
-
-    for (final className in config.importedClasses.keys) {
-      log.finest('Imported $className successfully.');
-    }
-
     ClassDecl resolve(String? binaryName) {
-      return config.importedClasses[binaryName] ??
+      return node.importedClasses[binaryName] ??
           node.decls[binaryName] ??
           resolve(DeclaredType.object.name);
     }
 
     DeclaredType.object.classDecl = resolve(DeclaredType.object.name);
-    final classLinker = _ClassLinker(
-      config,
-      resolve,
-    );
+    final classLinker = _ClassLinker(config, resolve);
     for (final classDecl in node.decls.values) {
       classDecl.accept(classLinker);
     }
   }
 }
 
-class _ClassLinker extends Visitor<ClassDecl, void> {
+class _ClassLinker extends ElementVisitor<ClassDecl, void> {
   final Config config;
   final _Resolver resolve;
   final Set<ClassDecl> linked;
 
-  /// Keeps track of the [TypeParam]s that introduced each type variable.
-  final typeVarOrigin = <String, TypeParam>{};
-
-  _ClassLinker(
-    this.config,
-    this.resolve,
-  ) : linked = {...config.importedClasses.values};
+  _ClassLinker(this.config, this.resolve) : linked = {};
 
   @override
   void visit(ClassDecl node) {
-    if (linked.contains(node)) return;
+    if (linked.contains(node) || node.isImported) return;
     log.finest('Linking ${node.binaryName}.');
     linked.add(node);
 
@@ -105,54 +100,46 @@
     node.outerClass?.accept(this);
 
     // Add type params of outer classes to the nested classes.
-    final allTypeParams = <TypeParam>[];
+    node.allTypeParams = [];
     if (!node.isStatic) {
-      allTypeParams.addAll(node.outerClass?.allTypeParams ?? []);
+      node.allTypeParams.addAll(
+        node.outerClass?.allTypeParams.map(
+              (typeParam) => typeParam.clone(until: GenerationStage.linker),
+            ) ??
+            [],
+      );
     }
-    allTypeParams.addAll(node.typeParams);
-    node.allTypeParams = allTypeParams;
+    node.allTypeParams.addAll(node.typeParams);
+
+    /// Keeps track of the [TypeParam]s that introduced each type variable.
+    final typeVarOrigin = <String, TypeParam>{};
     for (final typeParam in node.allTypeParams) {
       typeVarOrigin[typeParam.name] = typeParam;
     }
+
     final typeLinker = _TypeLinker(resolve, typeVarOrigin);
 
+    for (final typeParam in node.typeParams) {
+      typeParam.accept(_TypeParamLinker(typeLinker));
+      typeParam.parent = node;
+    }
+
     node.superclass ??= DeclaredType.object;
     node.superclass!.accept(typeLinker);
     final superclass = (node.superclass! as DeclaredType).classDecl;
     superclass.accept(this);
 
-    final methodSignatures = <String>{};
-    final methodLinker = _MethodLinker(config, resolve, {...typeVarOrigin});
+    final signatureToMethod = <String, Method>{};
     for (final method in node.methods) {
       method.classDecl = node;
-      method.accept(methodLinker);
-      methodSignatures.add(method.javaSig);
+      method.accept(_MethodLinker(config, resolve, {...typeVarOrigin}));
+      signatureToMethod[method.javaSig] = method;
     }
-    // Add all methods from the superinterfaces of this class.
+    // Add all methods from the superinterfaces and the superclass.
     if (node.methods.isEmpty) {
       // Make the list modifiable.
       node.methods = [];
     }
-    for (final interface in node.interfaces) {
-      interface.accept(typeLinker);
-      if (interface case final DeclaredType interfaceType) {
-        interfaceType.classDecl.accept(this);
-        for (final interfaceMethod in interfaceType.classDecl.methods) {
-          final clonedMethod =
-              interfaceMethod.clone(until: GenerationStage.linker);
-          clonedMethod.accept(_MethodMover(
-            typeVarOrigin: {...typeVarOrigin},
-            fromType: interfaceType,
-            toClass: node,
-          ));
-          if (!methodSignatures.contains(clonedMethod.javaSig)) {
-            clonedMethod.accept(methodLinker);
-            methodSignatures.add(clonedMethod.javaSig);
-            node.methods.add(clonedMethod);
-          }
-        }
-      }
-    }
 
     node.superCount = superclass.superCount + 1;
 
@@ -161,14 +148,60 @@
       field.classDecl = node;
       field.accept(fieldLinker);
     }
-    for (final typeParam in node.typeParams) {
-      typeParam.accept(_TypeParamLinker(typeLinker));
-      typeParam.parent = node;
+    final debug = node.binaryName ==
+        'com.github.dart_lang.jnigen.inheritance.DerivedInterface';
+    if (debug) log.warning('signatures: $signatureToMethod');
+    void moveMethod(Method method, DeclaredType fromType) {
+      if (signatureToMethod.containsKey(method.javaSig)) {
+        if (debug)
+          log.warning(
+              'signatures contain ${method.javaSig} from ${method.classDecl.binaryName}');
+        // If this method also exists in a super interface, the methods
+        // should share their sharedState.
+        final thisMethod = signatureToMethod[method.javaSig]!;
+        thisMethod.sharedState = method.sharedState;
+      } else {
+        if (debug)
+          log.warning(
+              'signatures do not contain ${method.javaSig} from ${method.classDecl.binaryName}');
+        final clonedMethod = method.clone(until: GenerationStage.linker);
+        clonedMethod.accept(_MethodMover(fromType: fromType, toClass: node));
+        clonedMethod.accept(_MethodLinker(config, resolve, {...typeVarOrigin}));
+        signatureToMethod[clonedMethod.javaSig] = clonedMethod;
+        node.methods.add(clonedMethod);
+      }
+    }
+
+    for (final interface in node.interfaces) {
+      interface.accept(typeLinker);
+      if (interface case final DeclaredType interfaceType) {
+        interfaceType.classDecl.accept(this);
+        for (final interfaceMethod in interfaceType.classDecl.methods) {
+          moveMethod(interfaceMethod, interfaceType);
+        }
+      }
+    }
+
+    void moveField(Field field) {
+      // FIXME
+    }
+
+    if (node.superclass case final DeclaredType superType?) {
+      for (final method in superclass.methods) {
+        if (!method.isStatic && !method.isConstructor) {
+          moveMethod(method, superType);
+        }
+      }
+      for (final field in superclass.fields) {
+        if (!field.isStatic) {
+          moveField(field);
+        }
+      }
     }
   }
 }
 
-class _MethodLinker extends Visitor<Method, void> {
+class _MethodLinker extends ElementVisitor<Method, void> {
   _MethodLinker(this.config, this.resolve, this.typeVarOrigin)
       : typeLinker = _TypeLinker(resolve, typeVarOrigin);
 
@@ -186,11 +219,12 @@
       final outerClassTypeParamCount = node.classDecl.allTypeParams.length -
           node.classDecl.typeParams.length;
       final outerClassTypeParams = [
-        for (final typeParam
-            in node.classDecl.allTypeParams.take(outerClassTypeParamCount)) ...[
+        for (final typeParam in node.classDecl.allTypeParams.take(
+          outerClassTypeParamCount,
+        )) ...[
           TypeVar(name: typeParam.name)
             ..annotations = [if (typeParam.hasNonNull) Annotation.nonNull],
-        ]
+        ],
       ];
       final outerClassType = DeclaredType(
         binaryName: node.classDecl.outerClass!.binaryName,
@@ -218,6 +252,11 @@
     for (final typeParam in node.typeParams) {
       typeVarOrigin[typeParam.name] = typeParam;
     }
+    final typeParamLinker = _TypeParamLinker(typeLinker);
+    for (final typeParam in node.typeParams) {
+      typeParam.accept(typeParamLinker);
+      typeParam.parent = node;
+    }
     node.descriptor = node.accept(_MethodDescriptor(typeVarOrigin));
     node.returnType.accept(typeLinker);
 
@@ -231,12 +270,7 @@
         ...?node.annotations,
       ];
     }
-    final typeParamLinker = _TypeParamLinker(typeLinker);
     final paramLinker = _ParamLinker(typeLinker);
-    for (final typeParam in node.typeParams) {
-      typeParam.accept(typeParamLinker);
-      typeParam.parent = node;
-    }
     for (final param in node.params) {
       param.accept(paramLinker);
       param.method = node;
@@ -297,14 +331,9 @@
   void visitPrimitiveType(PrimitiveType node) {
     // Do nothing.
   }
-
-  @override
-  void visitNonPrimitiveType(ReferredType node) {
-    // Do nothing.
-  }
 }
 
-class _FieldLinker extends Visitor<Field, void> {
+class _FieldLinker extends ElementVisitor<Field, void> {
   _FieldLinker(this.typeLinker);
 
   final _TypeLinker typeLinker;
@@ -316,18 +345,17 @@
     // `androidx.annotation.NonNull` only get applied to elements but not types.
     if (!node.type.hasNullabilityAnnotations &&
         node.hasNullabilityAnnotations) {
-      node.type.annotations = [
-        ...?node.type.annotations,
-        ...?node.annotations,
-      ];
+      node.type.annotations = [...?node.type.annotations, ...?node.annotations];
     }
     node.type.accept(typeLinker);
-    node.type.descriptor =
-        node.type.accept(_TypeDescriptor(typeLinker.typeVarOrigin));
+    node.descriptor ??= node.type.descriptor;
+    node.type.descriptor = node.type.accept(
+      _TypeDescriptor(typeLinker.typeVarOrigin),
+    );
   }
 }
 
-class _TypeParamLinker extends Visitor<TypeParam, void> {
+class _TypeParamLinker extends ElementVisitor<TypeParam, void> {
   _TypeParamLinker(this.typeLinker);
 
   final _TypeLinker typeLinker;
@@ -340,7 +368,7 @@
   }
 }
 
-class _ParamLinker extends Visitor<Param, void> {
+class _ParamLinker extends ElementVisitor<Param, void> {
   _ParamLinker(this.typeLinker);
 
   final _TypeLinker typeLinker;
@@ -352,10 +380,7 @@
     // `androidx.annotation.NonNull` only get applied to elements but not types.
     if (!node.type.hasNullabilityAnnotations &&
         node.hasNullabilityAnnotations) {
-      node.type.annotations = [
-        ...?node.type.annotations,
-        ...?node.annotations,
-      ];
+      node.type.annotations = [...?node.type.annotations, ...?node.annotations];
     }
     node.type.accept(typeLinker);
   }
@@ -364,19 +389,16 @@
 /// Once a [Method] is cloned and added to another [ClassDecl], the original
 /// type parameters can be replaced with other ones and its `classDecl` will be
 /// different. This visitor fixes these issues after the cloning is done.
-class _MethodMover extends Visitor<Method, void> {
-  final Map<String, TypeParam> typeVarOrigin;
+class _MethodMover extends ElementVisitor<Method, void> {
   final DeclaredType fromType;
   final ClassDecl toClass;
 
-  _MethodMover({
-    required this.typeVarOrigin,
-    required this.fromType,
-    required this.toClass,
-  });
+  _MethodMover({required this.fromType, required this.toClass});
 
   @override
   void visit(Method node) {
+    final b = node.javaSig == 'push(Ljava/lang/Object;)V';
+    if (b) log.warning('moving ${node.javaSig}...');
     node.classDecl = toClass;
     final typeMover = _TypeMover(fromType: fromType);
     if (node.returnType is TypeVar) {
@@ -386,7 +408,10 @@
     }
     for (final param in node.params) {
       if (param.type is TypeVar) {
+        if (b) log.warning('param ${param.name} is a type var');
+        if (b) log.warning('origin: ${(param.type as TypeVar).origin.parent}');
         param.type = typeMover.replaceTypeVar(param.type as TypeVar);
+        if (b) log.warning('now it became: ${param.type.name}');
       } else {
         param.type.accept(typeMover);
       }
@@ -400,15 +425,10 @@
         }
       }
     }
-    // Since the types can be changed, the descriptor can be changed as well.
-    for (final typeParam in node.typeParams) {
-      typeVarOrigin[typeParam.name] = typeParam;
-    }
-    node.descriptor = node.accept(_MethodDescriptor(typeVarOrigin));
   }
 }
 
-class _TypeMover extends TypeVisitor<void> {
+class _TypeMover extends TypeVisitor<void> with DefaultNonPrimitive {
   final DeclaredType fromType;
 
   _TypeMover({required this.fromType});
@@ -420,8 +440,9 @@
 
   ReferredType replaceTypeVar(TypeVar typeVar) {
     if (typeVar.origin.parent == fromType.classDecl) {
-      final index = fromType.classDecl.allTypeParams
-          .indexWhere((typeParam) => typeParam.name == typeVar.name);
+      final index = fromType.classDecl.allTypeParams.indexWhere(
+        (typeParam) => typeParam.name == typeVar.name,
+      );
       if (index != -1) {
         if (index >= fromType.params.length) {
           return DeclaredType.object.clone();
@@ -462,7 +483,7 @@
 ///
 /// https://docs.oracle.com/en/java/javase/18/docs/specs/jni/types.html#type-signatures
 /// Also see: [_TypeDescriptor]
-class _MethodDescriptor extends Visitor<Method, String> {
+class _MethodDescriptor extends ElementVisitor<Method, String> {
   final Map<String, TypeParam> typeVarOrigin;
 
   _MethodDescriptor(this.typeVarOrigin);
@@ -478,8 +499,9 @@
       s.write(desc);
     }
     s.write(')');
-    final returnTypeDesc =
-        node.returnType.accept(_TypeDescriptor(typeVarOrigin));
+    final returnTypeDesc = node.returnType.accept(
+      _TypeDescriptor(typeVarOrigin),
+    );
     node.returnType.descriptor = returnTypeDesc;
     s.write(returnTypeDesc);
     return s.toString();
@@ -489,7 +511,7 @@
 /// JVM representation of type signatures.
 ///
 /// https://docs.oracle.com/en/java/javase/18/docs/specs/jni/types.html#type-signatures
-class _TypeDescriptor extends TypeVisitor<String> {
+class _TypeDescriptor extends TypeVisitor<String> with DefaultNonPrimitive {
   final Map<String, TypeParam> typeVarOrigin;
 
   _TypeDescriptor(this.typeVarOrigin);
diff --git a/pkgs/jnigen/lib/src/bindings/printer.dart b/pkgs/jnigen/lib/src/bindings/printer.dart
index 392ce95..f5c53bc 100644
--- a/pkgs/jnigen/lib/src/bindings/printer.dart
+++ b/pkgs/jnigen/lib/src/bindings/printer.dart
@@ -1,7 +1,7 @@
 import '../elements/elements.dart';
 import 'visitor.dart';
 
-class Printer extends Visitor<Classes, void> {
+class Printer extends ElementVisitor<Classes, void> {
   const Printer();
   @override
   void visit(Classes node) {
@@ -13,7 +13,7 @@
   }
 }
 
-class _ClassPrinter extends Visitor<ClassDecl, void> {
+class _ClassPrinter extends ElementVisitor<ClassDecl, void> {
   const _ClassPrinter();
   @override
   void visit(ClassDecl node) {
@@ -31,7 +31,7 @@
   }
 }
 
-class _MethodPrinter extends Visitor<Method, void> {
+class _MethodPrinter extends ElementVisitor<Method, void> {
   const _MethodPrinter();
   @override
   void visit(Method node) {
@@ -48,7 +48,7 @@
   }
 }
 
-class _FieldPrinter extends Visitor<Field, void> {
+class _FieldPrinter extends ElementVisitor<Field, void> {
   const _FieldPrinter();
   @override
   void visit(Field node) {
@@ -58,7 +58,7 @@
   }
 }
 
-class _ParamPrinter extends Visitor<Param, void> {
+class _ParamPrinter extends ElementVisitor<Param, void> {
   const _ParamPrinter();
 
   @override
@@ -132,12 +132,9 @@
     printAnnotation(node);
     print('${' ' * depth}</*>');
   }
-
-  @override
-  void visitNonPrimitiveType(ReferredType node) {}
 }
 
-class _AnnotationPrinter extends Visitor<Annotation, void> {
+class _AnnotationPrinter extends ElementVisitor<Annotation, void> {
   int depth;
 
   _AnnotationPrinter(this.depth);
diff --git a/pkgs/jnigen/lib/src/bindings/renamer.dart b/pkgs/jnigen/lib/src/bindings/renamer.dart
deleted file mode 100644
index c1a8d85..0000000
--- a/pkgs/jnigen/lib/src/bindings/renamer.dart
+++ /dev/null
@@ -1,310 +0,0 @@
-// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import '../config/config.dart';
-import '../elements/elements.dart';
-import '../logging/logging.dart';
-import 'visitor.dart';
-
-class _Allowed {
-  static const none = 0;
-  static const fields = 1 << 0;
-  static const methods = 1 << 1;
-  static const classes = 1 << 2;
-  static const all = fields | methods | classes;
-}
-
-enum _ElementKind {
-  field,
-  method,
-  klass;
-
-  bool isAllowed(String identifier) {
-    return 1 << index & (_keywords[identifier] ?? _Allowed.all) != 0;
-  }
-}
-
-const _keywords = {
-  'abstract': _Allowed.fields | _Allowed.methods,
-  'assert': _Allowed.none,
-  'await': _Allowed.none, // Cannot be used in async context
-  'break': _Allowed.none,
-  'case': _Allowed.none,
-  'catch': _Allowed.none,
-  'class': _Allowed.none,
-  'const': _Allowed.none,
-  'continue': _Allowed.none,
-  'covariant': _Allowed.fields | _Allowed.methods,
-  'default': _Allowed.none,
-  'deferred': _Allowed.fields | _Allowed.methods,
-  'do': _Allowed.none,
-  'dynamic': _Allowed.fields | _Allowed.methods,
-  'else': _Allowed.none,
-  'enum': _Allowed.none,
-  'export': _Allowed.fields | _Allowed.methods,
-  'extends': _Allowed.none,
-  'extension': _Allowed.fields | _Allowed.methods,
-  'external': _Allowed.fields | _Allowed.methods,
-  'factory': _Allowed.fields | _Allowed.methods,
-  'false': _Allowed.none,
-  'final': _Allowed.none,
-  'finally': _Allowed.none,
-  'for': _Allowed.none,
-  'Function': _Allowed.fields | _Allowed.methods,
-  'if': _Allowed.none,
-  'implements': _Allowed.fields | _Allowed.methods,
-  'import': _Allowed.methods,
-  'in': _Allowed.none,
-  'interface': _Allowed.fields | _Allowed.methods,
-  'is': _Allowed.none,
-  'late': _Allowed.fields | _Allowed.methods,
-  'library': _Allowed.fields | _Allowed.methods,
-  'mixin': _Allowed.fields | _Allowed.methods,
-  'new': _Allowed.none,
-  'null': _Allowed.none,
-  'operator': _Allowed.fields | _Allowed.methods,
-  'part': _Allowed.fields | _Allowed.methods,
-  'required': _Allowed.fields | _Allowed.methods,
-  'rethrow': _Allowed.none,
-  'return': _Allowed.none,
-  'static': _Allowed.fields | _Allowed.methods,
-  'super': _Allowed.none,
-  'switch': _Allowed.none,
-  'this': _Allowed.none,
-  'throw': _Allowed.none,
-  'true': _Allowed.none,
-  'try': _Allowed.none,
-  'typedef': _Allowed.fields | _Allowed.methods,
-  'var': _Allowed.none,
-  'void': _Allowed.none,
-  'while': _Allowed.none,
-  'with': _Allowed.none,
-  'yield': _Allowed.none, // Cannot be used in async context
-};
-
-/// Methods & properties already defined by dart JObject base class.
-///
-/// If a second method or field has the same name, it will be appended by a
-/// numeric suffix.
-const Map<String, int> _definedSyms = {
-  'as': 1,
-  'fromReference': 1,
-  'toString': 1,
-  'hashCode': 1,
-  'runtimeType': 1,
-  'noSuchMethod': 1,
-  'reference': 1,
-  'isA': 1,
-  'isInstanceOf': 1,
-  'isReleased': 1,
-  'isNull': 1,
-  'use': 1,
-  'release': 1,
-  'releasedBy': 1,
-  'jClass': 1,
-  'type': 1,
-};
-
-String _preprocess(String name) {
-  // Replaces the `_` prefix with `$_` to prevent hiding public members in Dart.
-  // For example `_foo` -> `$_foo`.
-  String makePublic(String name) =>
-      name.startsWith('_') ? '\$_${name.substring(1)}' : name;
-
-  // Replaces each dollar sign with two dollar signs in [name].
-  // For example `$foo$$bar$` -> `$$foo$$$$bar$$`.
-  String doubleDollarSigns(String name) => name.replaceAll(r'$', r'$$');
-
-  return makePublic(doubleDollarSigns(name));
-}
-
-/// Appends `$` to [name] if [name] is a Dart keyword.
-///
-/// Examples:
-/// * `yield` -> `yield$`
-/// * `foo` -> `foo`
-String _keywordRename(String name, _ElementKind kind) =>
-    kind.isAllowed(name) ? name : '$name\$';
-
-String _renameConflict(
-    Map<String, int> counts, String name, _ElementKind kind) {
-  if (counts.containsKey(name)) {
-    final count = counts[name]!;
-    final renamed = '$name\$$count';
-    counts[name] = count + 1;
-    return renamed;
-  }
-  counts[name] = 1;
-  return _keywordRename(name, kind);
-}
-
-class Renamer extends Visitor<Classes, void> with TopLevelVisitor {
-  @override
-  final GenerationStage stage = GenerationStage.renamer;
-
-  final Config config;
-
-  Renamer(this.config);
-
-  @override
-  void visit(Classes node) {
-    final classRenamer = _ClassRenamer(config);
-
-    for (final classDecl in node.decls.values) {
-      classDecl.accept(classRenamer);
-    }
-  }
-}
-
-class _ClassRenamer implements Visitor<ClassDecl, void> {
-  final Config config;
-  final Set<ClassDecl> renamed;
-  final Map<String, int> topLevelNameCounts = {};
-  final Map<ClassDecl, Map<String, int>> nameCounts = {};
-
-  _ClassRenamer(
-    this.config,
-  ) : renamed = {...config.importedClasses.values};
-
-  @override
-  void visit(ClassDecl node) {
-    if (renamed.contains(node)) return;
-    log.finest('Renaming ${node.binaryName}.');
-    renamed.add(node);
-
-    nameCounts[node] = {..._definedSyms};
-    if (node.declKind == DeclKind.interfaceKind) {
-      nameCounts[node]!['implement'] = 1;
-      nameCounts[node]!['implementIn'] = 1;
-    }
-    node.methodNumsAfterRenaming = {};
-
-    final superClass = (node.superclass! as DeclaredType).classDecl;
-    superClass.accept(this);
-    nameCounts[node]!.addAll(nameCounts[superClass] ?? {});
-
-    if (node.outerClass case final outerClass?) {
-      outerClass.accept(this);
-    }
-
-    final outerClassName =
-        node.outerClass == null ? '' : '${node.outerClass!.finalName}\$';
-    final className =
-        '$outerClassName${_preprocess(node.userDefinedName ?? node.name)}';
-
-    // When generating all the classes in a single file
-    // the names need to be unique.
-    final uniquifyName =
-        config.outputConfig.dartConfig.structure == OutputStructure.singleFile;
-    node.finalName = uniquifyName
-        ? _renameConflict(topLevelNameCounts, className, _ElementKind.klass)
-        : className;
-
-    if (node.userDefinedName == null ||
-        node.userDefinedName == node.finalName) {
-      log.fine('Class ${node.binaryName} is named ${node.finalName}');
-    } else {
-      log.warning('Renaming Class ${node.binaryName} to ${node.userDefinedName}'
-          ' causes a name collision. Renamed to ${node.finalName} instead.');
-    }
-
-    // Rename fields before renaming methods. In case a method and a field have
-    // identical names, the field will keep its original name and the
-    // method will be renamed.
-    final fieldRenamer = _FieldRenamer(
-      config,
-      uniquifyName && node.isTopLevel ? topLevelNameCounts : nameCounts[node]!,
-    );
-    for (final field in node.fields) {
-      field.accept(fieldRenamer);
-    }
-
-    final methodRenamer = _MethodRenamer(
-      config,
-      uniquifyName && node.isTopLevel ? topLevelNameCounts : nameCounts[node]!,
-    );
-    for (final method in node.methods) {
-      method.accept(methodRenamer);
-    }
-  }
-}
-
-class _MethodRenamer implements Visitor<Method, void> {
-  _MethodRenamer(this.config, this.nameCounts);
-
-  final Config config;
-  final Map<String, int> nameCounts;
-
-  @override
-  void visit(Method node) {
-    final name = _preprocess(
-        node.userDefinedName ?? (node.isConstructor ? 'new' : node.name));
-    final sig = node.javaSig;
-    // If node is in super class, assign its number, overriding it.
-    final superClass = (node.classDecl.superclass! as DeclaredType).classDecl;
-    final superNum = superClass.methodNumsAfterRenaming[sig];
-    if (superNum != null) {
-      // Don't rename if superNum == 0
-      // Unless the node name is a keyword.
-      final superNumText = superNum == 0 ? '' : '$superNum';
-      final methodName =
-          superNum == 0 ? _keywordRename(name, _ElementKind.method) : name;
-      node.finalName = '$methodName$superNumText';
-      node.classDecl.methodNumsAfterRenaming[sig] = superNum;
-    } else {
-      node.finalName = _renameConflict(nameCounts, name, _ElementKind.method);
-      node.classDecl.methodNumsAfterRenaming[sig] = nameCounts[name]! - 1;
-    }
-
-    if (node.userDefinedName == null ||
-        node.userDefinedName == node.finalName) {
-      log.fine('Method ${node.classDecl.binaryName}#${node.name}'
-          ' is named ${node.finalName}');
-    } else {
-      log.warning('Renaming Method ${node.classDecl.binaryName}#'
-          '${node.name} to ${node.userDefinedName} cause a name collision. '
-          'Renamed to ${node.finalName} instead.');
-    }
-
-    final paramRenamer = _ParamRenamer(config);
-    for (final param in node.params) {
-      param.accept(paramRenamer);
-    }
-  }
-}
-
-class _FieldRenamer implements Visitor<Field, void> {
-  _FieldRenamer(this.config, this.nameCounts);
-
-  final Config config;
-  final Map<String, int> nameCounts;
-
-  @override
-  void visit(Field node) {
-    final fieldName = _preprocess(node.userDefinedName ?? node.name);
-    node.finalName = _renameConflict(nameCounts, fieldName, _ElementKind.field);
-
-    if (node.userDefinedName == null ||
-        node.userDefinedName == node.finalName) {
-      log.fine('Field ${node.classDecl.binaryName}#${node.name}'
-          ' is named ${node.finalName}');
-    } else {
-      log.warning('Renaming Field ${node.classDecl.binaryName}#${node.name}'
-          ' to ${node.userDefinedName} cause a name collision. '
-          'Renamed to ${node.finalName} instead.');
-    }
-  }
-}
-
-class _ParamRenamer implements Visitor<Param, void> {
-  _ParamRenamer(this.config);
-
-  final Config config;
-
-  @override
-  void visit(Param node) {
-    node.finalName =
-        _keywordRename(node.userDefinedName ?? node.name, _ElementKind.field);
-  }
-}
diff --git a/pkgs/jnigen/lib/src/bindings/resolver.dart b/pkgs/jnigen/lib/src/bindings/resolver.dart
deleted file mode 100644
index 25ba34d..0000000
--- a/pkgs/jnigen/lib/src/bindings/resolver.dart
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:math';
-
-import '../elements/elements.dart';
-import '../logging/logging.dart';
-
-class Resolver {
-  /// Class corresponding to currently writing file.
-  ///
-  /// Is `null` when in single file mode.
-  final String? currentClass;
-
-  /// Explicit import mappings.
-  final Map<String, ClassDecl> importedClasses;
-
-  /// Names of all classes in input.
-  final Set<String> inputClassNames;
-
-  final List<String> _importStrings = [];
-
-  final Set<String> _relativeImportedClasses = {};
-  final Map<String, String> _importedNameToClass = {
-    r'_$core': '',
-    r'_$jni': '',
-  };
-  final Map<String, String> _classToImportedName = {};
-
-  Resolver({
-    required this.importedClasses,
-    required this.currentClass,
-    this.inputClassNames = const {},
-  });
-
-  static String getFileClassName(String binaryName) {
-    final dollarSign = binaryName.indexOf('\$');
-    if (dollarSign != -1) {
-      return binaryName.substring(0, dollarSign);
-    }
-    return binaryName;
-  }
-
-  /// splits [str] into 2 from last occurence of [sep]
-  static List<String> cutFromLast(String str, String sep) {
-    final li = str.lastIndexOf(sep);
-    if (li == -1) {
-      return ['', str];
-    }
-    return [str.substring(0, li), str.substring(li + 1)];
-  }
-
-  /// Get the prefix for the class
-  String resolvePrefix(ClassDecl classDecl) {
-    if (classDecl.path == 'package:jni/jni.dart') {
-      return r'jni$_.';
-    }
-    final binaryName = classDecl.binaryName;
-    final target = getFileClassName(binaryName);
-
-    // For classes we generate (inside [inputClassNames]) no import
-    // (and therefore no prefix) is necessary when:
-    // * Never necessary in single file mode
-    // * In multi file mode if the target is the same as the current class
-    if ((currentClass == null || target == currentClass) &&
-        inputClassNames.contains(binaryName)) {
-      return '';
-    }
-
-    if (_classToImportedName.containsKey(target)) {
-      // This package was already resolved
-      // but we still need to check if it was a relative import, in which case
-      // the class not in inputClassNames cannot be mapped here.
-      if (!_relativeImportedClasses.contains(target) ||
-          inputClassNames.contains(binaryName)) {
-        final importedName = _classToImportedName[target];
-        return '$importedName.';
-      }
-    }
-
-    final classImport = getImport(target, binaryName);
-    log.finest('$target resolved to $classImport for $binaryName');
-    if (classImport == null) {
-      return '';
-    }
-
-    final pkgName = cutFromLast(target, '.')[1].toLowerCase();
-
-    // We always name imports with an underscore suffix, so that they can be
-    // never shadowed by a parameter or local variable.
-    var importedName = '$pkgName\$_';
-    var suffix = 0;
-    while (_importedNameToClass.containsKey(importedName)) {
-      ++suffix;
-      importedName = '$pkgName\$_$suffix';
-    }
-
-    _importedNameToClass[importedName] = target;
-    _classToImportedName[target] = importedName;
-    _importStrings.add("import '$classImport' as $importedName;\n");
-    return '$importedName.';
-  }
-
-  /// Returns import string for [classToResolve], or `null` if the class is not
-  /// found.
-  ///
-  /// [binaryName] is the class name trying to be resolved. This parameter is
-  /// requested so that classes included in current bindings can be resolved
-  /// using relative path.
-  String? getImport(String classToResolve, String binaryName) {
-    final prefix = classToResolve;
-
-    // short circuit if the requested class is specified directly in import map.
-    if (importedClasses.containsKey(binaryName)) {
-      return importedClasses[binaryName]!.path;
-    }
-
-    if (prefix.isEmpty) {
-      throw UnsupportedError('unexpected: empty package name.');
-    }
-
-    final dest = classToResolve.split('.');
-    final src = currentClass!.split('.');
-    // Use relative import when the required class is included in current set
-    // of bindings.
-    if (inputClassNames.contains(binaryName)) {
-      var common = 0;
-      // find the common prefix path directory of current package, and directory
-      // of target package
-      // src.length - 1 simply corresponds to directory of the package.
-      for (var i = 0; i < src.length - 1 && i < dest.length - 1; i++) {
-        if (src[i] == dest[i]) {
-          common++;
-        } else {
-          break;
-        }
-      }
-      final pathToCommon = '../' * ((src.length - 1) - common);
-      final pathToClass = dest.sublist(max(common, 0)).join('/');
-      _relativeImportedClasses.add(classToResolve);
-      return '$pathToCommon$pathToClass.dart';
-    }
-
-    return null;
-  }
-
-  List<String> get importStrings {
-    return _importStrings..sort();
-  }
-}
diff --git a/pkgs/jnigen/lib/src/bindings/visitor.dart b/pkgs/jnigen/lib/src/bindings/visitor.dart
index 7e360d4..b800156 100644
--- a/pkgs/jnigen/lib/src/bindings/visitor.dart
+++ b/pkgs/jnigen/lib/src/bindings/visitor.dart
@@ -4,30 +4,41 @@
 
 import '../elements/elements.dart';
 
-abstract class Visitor<T extends Element<T>, R> {
-  const Visitor();
+abstract class ElementVisitor<T extends Element<T>, R> {
+  const ElementVisitor();
 
   R visit(T node);
 }
 
-mixin TopLevelVisitor<R> on Visitor<Classes, R> {
+mixin TopLevelVisitor<R> on ElementVisitor<Classes, R> {
   GenerationStage get stage;
 }
 
 abstract class TypeVisitor<R> {
   const TypeVisitor();
 
-  R visitNonPrimitiveType(ReferredType node);
   R visitPrimitiveType(PrimitiveType node);
+  R visitArrayType(ArrayType node);
+  R visitDeclaredType(DeclaredType node);
+  R visitTypeVar(TypeVar node);
+  R visitWildcard(Wildcard node);
+}
+
+mixin DefaultNonPrimitive<R> on TypeVisitor<R> {
+  R visitNonPrimitiveType(ReferredType node);
+  @override
   R visitArrayType(ArrayType node) => visitNonPrimitiveType(node);
+  @override
   R visitDeclaredType(DeclaredType node) => visitNonPrimitiveType(node);
+  @override
   R visitTypeVar(TypeVar node) => visitNonPrimitiveType(node);
+  @override
   R visitWildcard(Wildcard node) => visitNonPrimitiveType(node);
 }
 
 extension MultiVisitor<T extends Element<T>> on Iterable<Element<T>> {
   /// Accepts all lazily. Remember to call `.toList()` or similar methods!
-  Iterable<R> accept<R>(Visitor<T, R> v) {
+  Iterable<R> accept<R>(ElementVisitor<T, R> v) {
     return map((e) => e.accept(v));
   }
 }
diff --git a/pkgs/jnigen/lib/src/config/config_types.dart b/pkgs/jnigen/lib/src/config/config_types.dart
index c4ee002..738b408 100644
--- a/pkgs/jnigen/lib/src/config/config_types.dart
+++ b/pkgs/jnigen/lib/src/config/config_types.dart
@@ -6,20 +6,13 @@
 
 import 'package:logging/logging.dart';
 import 'package:path/path.dart' as p;
-import 'package:pub_semver/pub_semver.dart';
-import 'package:yaml/yaml.dart';
 
-import '../elements/elements.dart';
-import '../elements/j_elements.dart' as j_ast;
 import '../logging/logging.dart';
-import '../util/find_package.dart';
+import '../transformers/graph.dart' show Visitor;
 import 'config_exception.dart';
 import 'experiments.dart';
 import 'yaml_reader.dart';
 
-/// Modify this when symbols file format changes according to pub_semver.
-final _currentVersion = Version(1, 0, 0);
-
 /// Configuration for dependencies to be downloaded using maven.
 ///
 /// Dependency names should be listed in groupId:artifactId:version format.
@@ -217,8 +210,8 @@
   final Uri path;
 
   SymbolsOutputConfig(this.path) {
-    if (p.extension(path.toFilePath()) != '.yaml') {
-      throw ConfigException('Symbol\'s output path must end with ".yaml".');
+    if (p.extension(path.toFilePath()) != '.json') {
+      throw ConfigException('Symbol\'s output path must end with ".json".');
     }
   }
 }
@@ -258,23 +251,24 @@
 
 /// Configuration for jnigen binding generation.
 class Config {
-  Config(
-      {required this.outputConfig,
-      required this.classes,
-      this.experiments,
-      this.sourcePath,
-      this.classPath,
-      this.preamble,
-      this.customClassBody,
-      this.androidSdkConfig,
-      this.mavenDownloads,
-      this.summarizerOptions,
-      this.nonNullAnnotations,
-      this.nullableAnnotations,
-      this.logLevel = Level.INFO,
-      this.dumpJsonTo,
-      this.imports,
-      this.visitors}) {
+  Config({
+    required this.outputConfig,
+    required this.classes,
+    this.experiments,
+    this.sourcePath,
+    this.classPath,
+    this.preamble,
+    this.customClassBody,
+    this.androidSdkConfig,
+    this.mavenDownloads,
+    this.summarizerOptions,
+    this.nonNullAnnotations,
+    this.nullableAnnotations,
+    this.logLevel = Level.INFO,
+    this.dumpJsonTo,
+    this.imports,
+    this.visitors,
+  }) {
     for (final className in classes) {
       _validateClassName(className);
     }
@@ -323,9 +317,6 @@
   /// List of dependencies.
   final List<Uri>? imports;
 
-  /// Call [importClasses] before using this.
-  late final Map<String, ClassDecl> importedClasses;
-
   /// Annotations specifying that this type is nullable.
   final List<String>? nullableAnnotations;
 
@@ -338,106 +329,8 @@
   /// Used for testing package:jnigen.
   final Map<String, String>? customClassBody;
 
-  // User custom visitors.
-  List<j_ast.Visitor>? visitors;
-
-  Future<void> importClasses() async {
-    importedClasses = {};
-    for (final import in [
-      // Implicitly importing package:jni symbols.
-      Uri.parse('package:jni/jni_symbols.yaml'),
-      ...?imports,
-    ]) {
-      // Getting the actual uri in case of package uris.
-      final Uri yamlUri;
-      final String importPath;
-      if (import.scheme == 'package') {
-        final packageName = import.pathSegments.first;
-        final packageRoot = await findPackageRoot(packageName);
-        if (packageRoot == null) {
-          log.fatal('package:$packageName was not found.');
-        }
-        yamlUri = packageRoot
-            .resolve('lib/')
-            .resolve(import.pathSegments.sublist(1).join('/'));
-        importPath = 'package:$packageName';
-      } else {
-        yamlUri = import;
-        importPath = ([...import.pathSegments]..removeLast()).join('/');
-      }
-      log.finest('Parsing yaml file in url $yamlUri.');
-      final YamlMap yaml;
-      try {
-        final symbolsFile = File.fromUri(yamlUri);
-        final content = symbolsFile.readAsStringSync();
-        yaml = loadYaml(content, sourceUrl: yamlUri) as YamlMap;
-      } catch (e, s) {
-        log.warning(e);
-        log.warning(s);
-        log.fatal('Error while parsing yaml file "$import".');
-      }
-      final version = Version.parse(yaml['version'] as String);
-      if (!VersionConstraint.compatibleWith(_currentVersion).allows(version)) {
-        log.fatal('"$import" is version "$version" which is not compatible with'
-            'the current JNIgen symbols version $_currentVersion');
-      }
-      final files = yaml['files'] as YamlMap;
-      for (final entry in files.entries) {
-        final filePath = entry.key as String;
-        final classes = entry.value as YamlMap;
-        for (final classEntry in classes.entries) {
-          final binaryName = classEntry.key as String;
-          final decl = classEntry.value as YamlMap;
-          if (importedClasses.containsKey(binaryName)) {
-            log.fatal(
-              'Re-importing "$binaryName" in "$import".\n'
-              'Try hiding the class in import.',
-            );
-          }
-          final classDecl = ClassDecl(
-            declKind: DeclKind.classKind,
-            binaryName: binaryName,
-          )
-            ..path = '$importPath/$filePath'
-            ..finalName = decl['name'] as String
-            ..superCount = decl['super_count'] as int
-            ..allTypeParams = []
-            // TODO(https://github.com/dart-lang/native/issues/746): include
-            // outerClass in the interop information.
-            ..outerClass = null;
-          for (final typeParamEntry
-              in (decl['type_params'] as YamlMap?)?.entries ??
-                  <MapEntry<dynamic, dynamic>>[]) {
-            final typeParamName = typeParamEntry.key as String;
-            final bounds = (typeParamEntry.value as YamlMap).entries.map((e) {
-              final boundName = e.key as String;
-              // Can only be DECLARED or TYPE_VARIABLE
-              if (!['DECLARED', 'TYPE_VARIABLE'].contains(e.value)) {
-                log.fatal(
-                  'Unsupported bound kind "${e.value}" for bound "$boundName" '
-                  'in type parameter "$typeParamName" '
-                  'of "$binaryName".',
-                );
-              }
-              final ReferredType type;
-              if ((e.value as String) == 'DECLARED') {
-                type = DeclaredType(binaryName: boundName);
-              } else {
-                type = TypeVar(name: boundName);
-              }
-              return type;
-            }).toList();
-            classDecl.allTypeParams.add(
-              TypeParam(name: typeParamName, bounds: bounds),
-            );
-          }
-          classDecl.methodNumsAfterRenaming =
-              (decl['methods'] as YamlMap?)?.cast() ?? {};
-          importedClasses[binaryName] = classDecl;
-        }
-      }
-    }
-  }
+  /// User-provided visitors used to transform the generated bindings.
+  List<Visitor>? visitors;
 
   /// Directory containing the YAML configuration file, if any.
   Uri? get configRoot => _configRoot;
diff --git a/pkgs/jnigen/lib/src/elements/elements.dart b/pkgs/jnigen/lib/src/elements/elements.dart
index 268d2d0..479bfbe 100644
--- a/pkgs/jnigen/lib/src/elements/elements.dart
+++ b/pkgs/jnigen/lib/src/elements/elements.dart
@@ -2,14 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:collection';
+
 import 'package:json_annotation/json_annotation.dart';
 import 'package:meta/meta.dart';
+import 'package:path/path.dart' as p;
 
-// Types to describe java API elements
-
-import '../bindings/kotlin_processor.dart';
-import '../bindings/linker.dart';
-import '../bindings/renamer.dart';
 import '../bindings/visitor.dart';
 
 part 'elements.g.dart';
@@ -19,11 +17,12 @@
   // The order of the enum elements must match the order in
   // `../generate_bindings.dart`.
   unprocessed,
-  userVisitors,
-  excluder,
+  importer,
   kotlinProcessor,
   linker,
-  renamer,
+  graphBuilder,
+  userTransformers,
+  exporter,
   dartGenerator;
 
   bool operator <=(GenerationStage stage) {
@@ -31,10 +30,118 @@
   }
 }
 
-abstract class Element<T extends Element<T>> {
-  const Element();
+base mixin Element<T extends Element<T>> {
+  R accept<R>(ElementVisitor<T, R> v);
+}
 
-  R accept<R>(Visitor<T, R> v);
+base mixin Annotated {
+  abstract List<Annotation>? annotations;
+
+  static final nullableAnnotations = [
+    // Taken from https://kotlinlang.org/docs/java-interop.html#nullability-annotations
+    'org.jetbrains.annotations.Nullable',
+    'org.jspecify.nullness.Nullable',
+    'com.android.annotations.Nullable',
+    'androidx.annotation.Nullable',
+    'android.support.annotations.Nullable',
+    'edu.umd.cs.findbugs.annotations.Nullable',
+    'org.eclipse.jdt.annotation.Nullable',
+    'lombok.Nullable',
+    'io.reactivex.rxjava3.annotations.Nullable',
+  ];
+  bool get hasNullable {
+    return annotations?.any(
+          (annotation) =>
+              nullableAnnotations.contains(annotation.binaryName) ||
+              annotation.binaryName == 'javax.annotation.Nullable' &&
+                  annotation.properties['when'] == 'ALWAYS',
+        ) ??
+        false;
+  }
+
+  static final nonNullAnnotations = [
+    // Taken from https://kotlinlang.org/docs/java-interop.html#nullability-annotations
+    'org.jetbrains.annotations.NotNull',
+    'org.jspecify.nullness.NonNull',
+    'com.android.annotations.NonNull',
+    'androidx.annotation.NonNull',
+    'android.support.annotations.NonNull',
+    'edu.umd.cs.findbugs.annotations.NonNull',
+    'org.eclipse.jdt.annotation.NonNull',
+    'lombok.NonNull',
+    'io.reactivex.rxjava3.annotations.NonNull',
+  ];
+  bool get hasNonNull {
+    return annotations?.any(
+          (annotation) =>
+              nonNullAnnotations.contains(annotation.binaryName) ||
+              annotation.binaryName == 'javax.annotation.Nonnull' &&
+                  annotation.properties['when'] == 'ALWAYS',
+        ) ??
+        false;
+  }
+
+  bool get hasNullabilityAnnotations => hasNonNull || hasNullable;
+
+  bool get isNullable {
+    if (hasNullable) {
+      return true;
+    }
+    return !hasNonNull;
+  }
+}
+
+base mixin HasModifiers<T extends Element<T>> on Element<T> {
+  Set<String> get modifiers;
+
+  bool get isAbstract => modifiers.contains('abstract');
+  bool get isStatic => modifiers.contains('static');
+  bool get isFinal => modifiers.contains('final');
+  bool get isPublic => modifiers.contains('public');
+  bool get isProtected => modifiers.contains('protected');
+  bool get isSynthetic => modifiers.contains('synthetic');
+  bool get isBridge => modifiers.contains('bridge');
+}
+
+base mixin Importable<T extends Element<T>> on Element<T> {
+  /// Whether this class has been imported from a different JNIgen-generated
+  /// package.
+  ///
+  /// Can be modified in [GenerationStage.importer].
+  @JsonKey(includeFromJson: false)
+  bool isImported = false;
+}
+
+/// Represents an element that could potentially be renamed.
+base mixin Renamable<T extends Element<T>> on Element<T> {
+  /// The name used in JVM bytecode or Java source.
+  ///
+  /// Might be different to [originalName] for Kotlin code.
+  @JsonKey(includeFromJson: false)
+  String get name;
+
+  /// Defaults to [name] but will be changed to the original Kotlin name of the
+  /// element in [GenerationStage.kotlinProcessor] if it has originated from
+  /// Kotlin.
+  @JsonKey(includeFromJson: false)
+  late String originalName = name;
+
+  /// The name loaded from the API stability file.
+  ///
+  /// Populated in [GenerationStage.importer].
+  @JsonKey(includeFromJson: false)
+  // FIXME
+  late final String? stableName = null;
+
+  /// The name used in the generated bindings.
+  @JsonKey(includeFromJson: false)
+  String? finalName;
+}
+
+base mixin Excludable<T extends Element<T>> on Element<T> {
+  /// Whether this element is excluded from the generated bindings.
+  @JsonKey(includeFromJson: false)
+  bool isExcluded = false;
 }
 
 /// A kind describes the type of a declaration.
@@ -48,11 +155,18 @@
   enumKind,
 }
 
-class Classes implements Element<Classes> {
-  const Classes(this.decls);
+final class Classes with Element<Classes> {
+  Classes(this.decls);
 
   final Map<String, ClassDecl> decls;
 
+  /// Populated in [GenerationStage.importer].
+  final Map<String, ClassDecl> importedClasses = {};
+
+  /// Populated in [GenerationStage.linker].
+  final Map<String, DartFile> files =
+      HashMap(equals: p.equals, hashCode: p.hash);
+
   factory Classes.fromJson(List<dynamic> json) {
     final decls = <String, ClassDecl>{};
     for (final declJson in json) {
@@ -63,7 +177,20 @@
   }
 
   @override
-  R accept<R>(Visitor<Classes, R> v) {
+  R accept<R>(ElementVisitor<Classes, R> v) {
+    return v.visit(this);
+  }
+}
+
+final class DartFile with Element<DartFile>, Importable {
+  final String path;
+  final Map<String, ClassDecl> classes;
+  final List<DartFile> exports = [];
+
+  DartFile(this.path, this.classes);
+
+  @override
+  R accept<R>(ElementVisitor<DartFile, R> v) {
     return v.visit(this);
   }
 }
@@ -73,9 +200,15 @@
 // option in java.
 
 @JsonSerializable(createToJson: false)
-class ClassDecl with ClassMember, Annotated implements Element<ClassDecl> {
+final class ClassDecl
+    with
+        Element<ClassDecl>,
+        HasModifiers,
+        Annotated,
+        Renamable,
+        Excludable,
+        Importable {
   ClassDecl({
-    this.isExcluded = false,
     this.annotations,
     this.javadoc,
     required this.declKind,
@@ -92,12 +225,6 @@
     this.kotlinPackage,
   });
 
-  @JsonKey(includeFromJson: false)
-  bool isExcluded;
-
-  @JsonKey(includeFromJson: false)
-  String? userDefinedName;
-
   @override
   final Set<String> modifiers;
 
@@ -108,19 +235,25 @@
   final JavaDocComment? javadoc;
   final DeclKind declKind;
   final String binaryName;
+
+  /// The type parameters introduced by this exact class.
+  ///
+  /// Does not contain the type parameters of any outer-classes if this class
+  /// is a non-static inner-class. For a list of all type parameters including
+  /// the ones from the outer-classes, use [allTypeParams].
   List<TypeParam> typeParams;
   List<Method> methods;
   List<Field> fields;
   final List<ReferredType> interfaces;
 
-  /// Will default to java.lang.Object if null by [Linker].
+  /// Will default to java.lang.Object if null in [GenerationStage.linker].
   ReferredType? superclass;
 
   final String? outerClassBinaryName;
 
   /// Outer class's [ClassDecl] obtained from [outerClassBinaryName].
   ///
-  /// Populated by [Linker].
+  /// Populated in [GenerationStage.linker].
   @JsonKey(includeFromJson: false)
   late ClassDecl? outerClass;
 
@@ -134,16 +267,17 @@
 
   /// The number of super classes this type has.
   ///
-  /// Populated by [Linker].
+  /// Populated in [GenerationStage.linker].
   @JsonKey(includeFromJson: false)
   late int superCount;
 
-  /// Final name of this class.
+  /// Classes can have custom added fields and methods. This is used to ensure
+  /// the identifiers of these extra members do not collide with the other
+  /// identifiers present in the class.
   ///
-  /// Populated by [Renamer].
+  /// Populated in [GenerationStage.importer].
   @JsonKey(includeFromJson: false)
-  @override
-  late String finalName;
+  final Set<String> extraMembers = {};
 
   /// Name of the type class.
   @JsonKey(includeFromJson: false)
@@ -156,23 +290,17 @@
   ///
   /// For `Foo<T>.Bar<U, V>.Baz<W>` it is [T, U, V, W].
   ///
-  /// Populated by [Linker].
+  /// Populated in [GenerationStage.linker].
   @JsonKey(includeFromJson: false)
   late List<TypeParam> allTypeParams;
 
-  /// The path which this class is generated in.
+  /// The file which this class is generated in.
   ///
-  /// Populated by [Linker].
+  /// Populated in [GenerationStage.linker].
   @JsonKey(includeFromJson: false)
-  late String path;
+  late DartFile file;
 
-  /// The numeric suffix of the methods.
-  ///
-  /// Populated by [Renamer].
-  @JsonKey(includeFromJson: false)
-  late Map<String, int> methodNumsAfterRenaming;
-
-  /// Populated by [Linker].
+  /// Populated in [GenerationStage.linker].
   @JsonKey(includeFromJson: false)
   final Map<Operator, Method> operators = {};
 
@@ -183,7 +311,7 @@
   ///
   /// Used for overloading comparison operators.
   ///
-  /// Populated by [Linker].
+  /// Populated in [GenerationStage.linker].
   @JsonKey(includeFromJson: false)
   Method? compareTo;
 
@@ -198,13 +326,10 @@
       _$ClassDeclFromJson(json);
 
   @override
-  R accept<R>(Visitor<ClassDecl, R> v) {
+  R accept<R>(ElementVisitor<ClassDecl, R> v) {
     return v.visit(this);
   }
 
-  @override
-  ClassDecl get classDecl => this;
-
   /// Simple name of this class without the outerclasses.
   ///
   /// This is not uniquely identifiable from the [binaryName]. For instance,
@@ -222,8 +347,19 @@
   @JsonKey(includeFromJson: false)
   bool get isNested => outerClassBinaryName != null;
 
-  /// Whether the class is actually only a number of top-level Kotlin Functions.
-  bool get isTopLevel => kotlinPackage != null;
+  /// Whether the class is actually only a number of top-level Kotlin Functions
+  /// and properties.
+  @JsonKey(includeFromJson: false)
+  late bool isTopLevel = kotlinPackage != null;
+}
+
+@JsonEnum(fieldRename: FieldRename.screamingSnake, alwaysCreate: true)
+enum TypeKind {
+  primitive,
+  typeVariable,
+  wildcard,
+  declared,
+  array,
 }
 
 sealed class ReferredType with Annotated {
@@ -231,7 +367,7 @@
 
   String get name;
 
-  /// Populated by [Linker].
+  /// Populated in [GenerationStage.linker].
   @JsonKey(includeFromJson: false)
   String? descriptor;
 
@@ -239,29 +375,28 @@
   // we have to temporarily store `type` in a JSON map, and switch on the
   // enum value received.
   factory ReferredType.fromJson(Map<String, dynamic> json) {
-    final kind = json['kind'] as String;
+    final kind = $enumDecode(_$TypeKindEnumMap, json['kind']);
     final typeJson = json['type'] as Map<String, dynamic>;
     switch (kind) {
-      case 'PRIMITIVE':
+      case TypeKind.primitive:
         return PrimitiveType.fromJson(typeJson);
-      case 'TYPE_VARIABLE':
+      case TypeKind.typeVariable:
         return TypeVar.fromJson(typeJson);
-      case 'WILDCARD':
+      case TypeKind.wildcard:
         return Wildcard.fromJson(typeJson);
-      case 'DECLARED':
+      case TypeKind.declared:
         return DeclaredType.fromJson(typeJson);
-      case 'ARRAY':
+      case TypeKind.array:
         return ArrayType.fromJson(typeJson);
     }
-    throw UnsupportedError('The referred type of kind $kind is not supported');
   }
 
   R accept<R>(TypeVisitor<R> v);
 
-  ReferredType clone({GenerationStage until = GenerationStage.userVisitors});
+  ReferredType clone({GenerationStage until = GenerationStage.unprocessed});
 }
 
-class PrimitiveType extends ReferredType {
+final class PrimitiveType extends ReferredType {
   static final _primitives = {
     'byte': PrimitiveType._(
       name: 'byte',
@@ -371,7 +506,7 @@
   }
 
   @override
-  PrimitiveType clone({GenerationStage until = GenerationStage.userVisitors}) {
+  PrimitiveType clone({GenerationStage until = GenerationStage.unprocessed}) {
     final cloned = PrimitiveType._(
       boxedName: boxedName,
       cType: cType,
@@ -388,7 +523,7 @@
 }
 
 @JsonSerializable(createToJson: false)
-class DeclaredType extends ReferredType {
+final class DeclaredType extends ReferredType {
   static final object = DeclaredType(binaryName: 'java.lang.Object');
 
   DeclaredType({
@@ -428,7 +563,7 @@
       params.any((param) => param.hasNullabilityAnnotations);
 
   @override
-  DeclaredType clone({GenerationStage until = GenerationStage.userVisitors}) {
+  DeclaredType clone({GenerationStage until = GenerationStage.unprocessed}) {
     final cloned = DeclaredType(
       binaryName: binaryName,
       annotations: [...?annotations],
@@ -442,8 +577,8 @@
 }
 
 @JsonSerializable(createToJson: false)
-class TypeVar extends ReferredType {
-  /// Populated by [Linker].
+final class TypeVar extends ReferredType {
+  /// Populated in [GenerationStage.linker].
   @JsonKey(includeFromJson: false)
   late TypeParam origin;
 
@@ -498,7 +633,7 @@
   }
 
   @override
-  TypeVar clone({GenerationStage until = GenerationStage.userVisitors}) {
+  TypeVar clone({GenerationStage until = GenerationStage.unprocessed}) {
     final cloned = TypeVar(name: name, annotations: [...?annotations]);
     if (GenerationStage.linker <= until) {
       cloned.origin = origin;
@@ -509,7 +644,7 @@
 }
 
 @JsonSerializable(createToJson: false)
-class Wildcard extends ReferredType {
+final class Wildcard extends ReferredType {
   Wildcard({this.extendsBound, this.superBound, this.annotations});
   ReferredType? extendsBound;
   ReferredType? superBound;
@@ -552,7 +687,7 @@
       (extendsBound?.hasNullabilityAnnotations ?? false);
 
   @override
-  Wildcard clone({GenerationStage until = GenerationStage.userVisitors}) {
+  Wildcard clone({GenerationStage until = GenerationStage.unprocessed}) {
     final cloned = Wildcard(
       annotations: [...?annotations],
       extendsBound: extendsBound?.clone(until: until),
@@ -566,7 +701,7 @@
 }
 
 @JsonSerializable(createToJson: false)
-class ArrayType extends ReferredType {
+final class ArrayType extends ReferredType {
   ArrayType({required this.elementType, this.annotations});
   ReferredType elementType;
 
@@ -592,7 +727,7 @@
       super.hasNullabilityAnnotations || elementType.hasNullabilityAnnotations;
 
   @override
-  ArrayType clone({GenerationStage until = GenerationStage.userVisitors}) {
+  ArrayType clone({GenerationStage until = GenerationStage.unprocessed}) {
     final cloned = ArrayType(
       elementType: elementType.clone(until: until),
       annotations: [...?annotations],
@@ -604,82 +739,25 @@
   }
 }
 
-mixin Annotated {
-  abstract List<Annotation>? annotations;
+/// This class represents the shared state of all [Method]s of the same name and
+/// signature within a class hierarchy.
+final class SharedMethodState {
+  String? finalName;
+  bool isExcluded = false;
 
-  static final nullableAnnotations = [
-    // Taken from https://kotlinlang.org/docs/java-interop.html#nullability-annotations
-    'org.jetbrains.annotations.Nullable',
-    'org.jspecify.nullness.Nullable',
-    'com.android.annotations.Nullable',
-    'androidx.annotation.Nullable',
-    'android.support.annotations.Nullable',
-    'edu.umd.cs.findbugs.annotations.Nullable',
-    'org.eclipse.jdt.annotation.Nullable',
-    'lombok.Nullable',
-    'io.reactivex.rxjava3.annotations.Nullable',
-  ];
-  bool get hasNullable {
-    return annotations?.any(
-          (annotation) =>
-              nullableAnnotations.contains(annotation.binaryName) ||
-              annotation.binaryName == 'javax.annotation.Nullable' &&
-                  annotation.properties['when'] == 'ALWAYS',
-        ) ??
-        false;
-  }
-
-  static final nonNullAnnotations = [
-    // Taken from https://kotlinlang.org/docs/java-interop.html#nullability-annotations
-    'org.jetbrains.annotations.NotNull',
-    'org.jspecify.nullness.NonNull',
-    'com.android.annotations.NonNull',
-    'androidx.annotation.NonNull',
-    'android.support.annotations.NonNull',
-    'edu.umd.cs.findbugs.annotations.NonNull',
-    'org.eclipse.jdt.annotation.NonNull',
-    'lombok.NonNull',
-    'io.reactivex.rxjava3.annotations.NonNull',
-  ];
-  bool get hasNonNull {
-    return annotations?.any(
-          (annotation) =>
-              nonNullAnnotations.contains(annotation.binaryName) ||
-              annotation.binaryName == 'javax.annotation.Nonnull' &&
-                  annotation.properties['when'] == 'ALWAYS',
-        ) ??
-        false;
-  }
-
-  bool get hasNullabilityAnnotations => hasNonNull || hasNullable;
-
-  bool get isNullable {
-    if (hasNullable) {
-      return true;
-    }
-    return !hasNonNull;
-  }
-}
-
-mixin ClassMember {
-  String get name;
-  ClassDecl get classDecl;
-  Set<String> get modifiers;
-  String get finalName;
-
-  bool get isAbstract => modifiers.contains('abstract');
-  bool get isStatic => modifiers.contains('static');
-  bool get isFinal => modifiers.contains('final');
-  bool get isPublic => modifiers.contains('public');
-  bool get isProtected => modifiers.contains('protected');
-  bool get isSynthetic => modifiers.contains('synthetic');
-  bool get isBridge => modifiers.contains('bridge');
+  SharedMethodState();
 }
 
 @JsonSerializable(createToJson: false)
-class Method with ClassMember, Annotated implements Element<Method> {
+final class Method
+    with
+        Element<Method>,
+        HasModifiers,
+        Annotated,
+        Renamable,
+        Excludable,
+        Importable {
   Method({
-    this.userDefinedIsExcluded = false,
     this.annotations,
     this.javadoc,
     this.modifiers = const {},
@@ -690,8 +768,11 @@
     required this.returnType,
   });
 
+  /// The original name in the bytecode or Java source. Might be different to
+  /// [originalName] for Kotlin methods.
   @override
   final String name;
+
   @override
   final Set<String> modifiers;
   @override
@@ -701,56 +782,66 @@
   List<Param> params;
   ReferredType returnType;
 
-  /// Populated by user-defined visitors.
-  @JsonKey(includeFromJson: false)
-  bool userDefinedIsExcluded;
-
-  /// Populated by user-defined visitors.
-  @JsonKey(includeFromJson: false)
-  String? userDefinedName;
-
-  /// Populated by [KotlinProcessor].
+  /// Populated in [GenerationStage.kotlinProcessor].
   @JsonKey(includeFromJson: false)
   KotlinFunction? kotlinFunction;
 
   /// The actual return type when the method is a Kotlin's suspend fun.
   ///
-  /// Populated by [KotlinProcessor].
+  /// Populated in [GenerationStage.kotlinProcessor].
   @JsonKey(includeFromJson: false)
   ReferredType? asyncReturnType;
 
   /// The [ClassDecl] where this method is defined.
   ///
-  /// Populated by [Linker].
+  /// Populated in [GenerationStage.linker].
+  @JsonKey(includeFromJson: false)
+  late ClassDecl classDecl;
+
+  /// Populated in [GenerationStage.linker].
+  @JsonKey(includeFromJson: false)
+  late SharedMethodState sharedState = SharedMethodState();
+
   @JsonKey(includeFromJson: false)
   @override
-  late ClassDecl classDecl;
+  // ignore: overridden_fields
+  late String originalName = name == '<init>' ? 'new' : name;
+
+  @override
+  String? get finalName => sharedState.finalName;
+
+  @override
+  set finalName(String? finalName) {
+    sharedState.finalName = finalName;
+  }
+
+  @override
+  bool get isExcluded => sharedState.isExcluded;
+
+  @override
+  set isExcluded(bool isExcluded) {
+    sharedState.isExcluded = isExcluded;
+  }
 
   /// Can be used to match with [KotlinFunction]'s descriptor.
   ///
   /// Can create a unique signature in combination with [name].
-  /// Populated either by the ASM backend or [Linker].
+  /// Populated either by the ASM backend or in [GenerationStage.linker].
   String? descriptor;
 
   @JsonKey(includeFromJson: false)
   late String javaSig = '$name$descriptor';
 
-  /// Populated by [Renamer].
-  @JsonKey(includeFromJson: false)
-  @override
-  late String finalName;
-
   bool get isConstructor => name == '<init>';
 
   factory Method.fromJson(Map<String, dynamic> json) => _$MethodFromJson(json);
 
-  Method clone({GenerationStage until = GenerationStage.userVisitors}) {
+  Method clone({GenerationStage until = GenerationStage.unprocessed}) {
     final cloned = Method(
       name: name,
       returnType: returnType.clone(until: until),
       annotations: [...?annotations],
       descriptor: descriptor,
-      userDefinedIsExcluded: userDefinedIsExcluded,
       javadoc: javadoc,
       modifiers: {...modifiers},
       params: params.map((param) => param.clone(until: until)).toList(),
@@ -762,10 +853,13 @@
     // properties of the previous steps.
     switch (until) {
       case GenerationStage.dartGenerator:
-      case GenerationStage.renamer:
+      case GenerationStage.exporter:
+      case GenerationStage.userTransformers:
+        cloned.isExcluded = isExcluded;
         cloned.finalName = finalName;
-        continue linker;
-      linker:
+        continue graphBuilder;
+      graphBuilder:
+      case GenerationStage.graphBuilder:
       case GenerationStage.linker:
         cloned.descriptor = descriptor;
         cloned.classDecl = classDecl;
@@ -775,30 +869,28 @@
         for (final typeParam in cloned.typeParams) {
           typeParam.parent = cloned;
         }
+        cloned.sharedState = sharedState;
         continue kotlinProcessor;
       kotlinProcessor:
       case GenerationStage.kotlinProcessor:
         cloned.kotlinFunction = kotlinFunction;
         cloned.asyncReturnType = asyncReturnType;
-        continue excluder;
-      excluder:
-      case GenerationStage.excluder:
-      case GenerationStage.userVisitors:
-        cloned.userDefinedIsExcluded = userDefinedIsExcluded;
-        cloned.userDefinedName = userDefinedName;
+        continue importer;
+      importer:
+      case GenerationStage.importer:
       case GenerationStage.unprocessed:
     }
     return cloned;
   }
 
   @override
-  R accept<R>(Visitor<Method, R> v) {
+  R accept<R>(ElementVisitor<Method, R> v) {
     return v.visit(this);
   }
 }
 
 @JsonSerializable(createToJson: false)
-class Param with Annotated implements Element<Param> {
+final class Param with Element<Param>, Annotated, Renamable, Importable {
   Param({
     this.annotations,
     this.javadoc,
@@ -806,9 +898,6 @@
     required this.type,
   });
 
-  @JsonKey(includeFromJson: false)
-  String? userDefinedName;
-
   @override
   List<Annotation>? annotations;
   final JavaDocComment? javadoc;
@@ -817,22 +906,19 @@
   bool get isNullable => type.isNullable || super.hasNullable;
 
   // Synthetic methods might not have parameter names.
+  @override
   @JsonKey(defaultValue: 'synthetic')
   final String name;
 
   ReferredType type;
 
-  /// Populated by [Linker].
+  /// Populated in [GenerationStage.linker].
   @JsonKey(includeFromJson: false)
   late Method method;
 
-  /// Populated by [Renamer].
-  @JsonKey(includeFromJson: false)
-  late String finalName;
-
   factory Param.fromJson(Map<String, dynamic> json) => _$ParamFromJson(json);
 
-  Param clone({GenerationStage until = GenerationStage.userVisitors}) {
+  Param clone({GenerationStage until = GenerationStage.unprocessed}) {
     final cloned = Param(
       name: name,
       type: type,
@@ -842,36 +928,46 @@
     if (GenerationStage.linker <= until) {
       cloned.method = method;
     }
-    if (GenerationStage.renamer <= until) {
+    if (GenerationStage.userTransformers <= until) {
       cloned.finalName = finalName;
     }
     return cloned;
   }
 
   @override
-  R accept<R>(Visitor<Param, R> v) {
+  R accept<R>(ElementVisitor<Param, R> v) {
     return v.visit(this);
   }
 }
 
+/// This class represents the shared state of all [Field]s of the same name and
+/// type within a class hierarchy.
+final class SharedFieldState {
+  String? finalName;
+  bool isExcluded = false;
+
+  SharedFieldState();
+}
+
 @JsonSerializable(createToJson: false)
-class Field with ClassMember, Annotated implements Element<Field> {
+final class Field
+    with
+        Element<Field>,
+        HasModifiers,
+        Annotated,
+        Renamable,
+        Excludable,
+        Importable {
   Field({
-    this.isExcluded = false,
     this.annotations,
     this.javadoc,
     this.modifiers = const {},
     required this.name,
     required this.type,
+    required this.descriptor,
     this.defaultValue,
   });
 
-  @JsonKey(includeFromJson: false)
-  bool isExcluded;
-
-  @JsonKey(includeFromJson: false)
-  String? userDefinedName;
-
   @override
   final String name;
   @override
@@ -883,28 +979,40 @@
   final ReferredType type;
   final Object? defaultValue;
 
+  /// Can be used to match with [KotlinFunction]'s descriptor.
+  ///
+  /// Can create a unique signature in combination with [name].
+  /// Populated either by the ASM backend or in [GenerationStage.linker].
+  String? descriptor;
+
   /// The [ClassDecl] where this field is defined.
   ///
-  /// Populated by [Linker].
+  /// Populated in [GenerationStage.linker].
   @JsonKey(includeFromJson: false)
-  @override
   late ClassDecl classDecl;
 
-  /// Populated by [Renamer].
+  /// Populated in [GenerationStage.linker].
   @JsonKey(includeFromJson: false)
+  late SharedFieldState sharedState = SharedFieldState();
+
   @override
-  late String finalName;
+  String? get finalName => sharedState.finalName;
+
+  @override
+  set finalName(String? finalName) {
+    sharedState.finalName = finalName;
+  }
 
   factory Field.fromJson(Map<String, dynamic> json) => _$FieldFromJson(json);
 
   @override
-  R accept<R>(Visitor<Field, R> v) {
+  R accept<R>(ElementVisitor<Field, R> v) {
     return v.visit(this);
   }
 }
 
 @JsonSerializable(createToJson: false)
-class TypeParam with Annotated implements Element<TypeParam> {
+final class TypeParam with Element<TypeParam>, Annotated {
   TypeParam({required this.name, this.bounds = const [], this.annotations});
 
   final String name;
@@ -920,15 +1028,15 @@
 
   /// Can either be a [ClassDecl] or a [Method].
   ///
-  /// Populated by [Linker].
+  /// Populated in [GenerationStage.linker].
   @JsonKey(includeFromJson: false)
-  late ClassMember parent;
+  late HasModifiers parent;
 
   factory TypeParam.fromJson(Map<String, dynamic> json) =>
       _$TypeParamFromJson(json);
 
   /// Set [parent] after cloning.
-  TypeParam clone({GenerationStage until = GenerationStage.userVisitors}) {
+  TypeParam clone({GenerationStage until = GenerationStage.unprocessed}) {
     final cloned = TypeParam(
       name: name,
       annotations: [...?annotations],
@@ -941,13 +1049,13 @@
   }
 
   @override
-  R accept<R>(Visitor<TypeParam, R> v) {
+  R accept<R>(ElementVisitor<TypeParam, R> v) {
     return v.visit(this);
   }
 }
 
 @JsonSerializable(createToJson: false)
-class JavaDocComment implements Element<JavaDocComment> {
+final class JavaDocComment with Element<JavaDocComment> {
   JavaDocComment({this.comment = ''});
 
   final String comment;
@@ -956,7 +1064,7 @@
       _$JavaDocCommentFromJson(json);
 
   @override
-  R accept<R>(Visitor<JavaDocComment, R> v) {
+  R accept<R>(ElementVisitor<JavaDocComment, R> v) {
     return v.visit(this);
   }
 }
@@ -998,7 +1106,7 @@
   return typePaths;
 }
 
-sealed class TypePathStep {
+final class TypePathStep {
   const TypePathStep();
 }
 
@@ -1044,7 +1152,7 @@
 }
 
 @JsonSerializable(createToJson: false)
-class Annotation implements Element<Annotation> {
+final class Annotation with Element<Annotation> {
   /// Specifies that this type can be null.
   static const Annotation nullable =
       // Any other valid `Nullable` annotation would work.
@@ -1071,13 +1179,13 @@
       _$AnnotationFromJson(json);
 
   @override
-  R accept<R>(Visitor<Annotation, R> v) {
+  R accept<R>(ElementVisitor<Annotation, R> v) {
     return v.visit(this);
   }
 }
 
 @JsonSerializable(createToJson: false)
-class KotlinClass implements Element<KotlinClass> {
+final class KotlinClass with Element<KotlinClass> {
   KotlinClass({
     required this.name,
     required this.moduleName,
@@ -1118,13 +1226,13 @@
       _$KotlinClassFromJson(json);
 
   @override
-  R accept<R>(Visitor<KotlinClass, R> v) {
+  R accept<R>(ElementVisitor<KotlinClass, R> v) {
     return v.visit(this);
   }
 }
 
 @JsonSerializable(createToJson: false)
-class KotlinPackage implements Element<KotlinPackage> {
+final class KotlinPackage with Element<KotlinPackage> {
   KotlinPackage({this.functions = const [], this.properties = const []});
 
   final List<KotlinFunction> functions;
@@ -1134,13 +1242,13 @@
       _$KotlinPackageFromJson(json);
 
   @override
-  R accept<R>(Visitor<KotlinPackage, R> v) {
+  R accept<R>(ElementVisitor<KotlinPackage, R> v) {
     return v.visit(this);
   }
 }
 
 @JsonSerializable(createToJson: false)
-class KotlinFunction {
+final class KotlinFunction {
   KotlinFunction({
     required this.name,
     required this.descriptor,
@@ -1184,7 +1292,7 @@
 }
 
 @JsonSerializable(createToJson: false)
-class KotlinConstructor implements Element<KotlinConstructor> {
+final class KotlinConstructor with Element<KotlinConstructor> {
   KotlinConstructor({
     required this.name,
     required this.descriptor,
@@ -1201,13 +1309,13 @@
       _$KotlinConstructorFromJson(json);
 
   @override
-  R accept<R>(Visitor<KotlinConstructor, R> v) {
+  R accept<R>(ElementVisitor<KotlinConstructor, R> v) {
     return v.visit(this);
   }
 }
 
 @JsonSerializable(createToJson: false)
-class KotlinProperty implements Element<KotlinProperty> {
+final class KotlinProperty with Element<KotlinProperty> {
   KotlinProperty({
     this.fieldName,
     this.fieldDescriptor,
@@ -1255,13 +1363,13 @@
       _$KotlinPropertyFromJson(json);
 
   @override
-  R accept<R>(Visitor<KotlinProperty, R> v) {
+  R accept<R>(ElementVisitor<KotlinProperty, R> v) {
     return v.visit(this);
   }
 }
 
 @JsonSerializable(createToJson: false)
-class KotlinType implements Element<KotlinType> {
+final class KotlinType with Element<KotlinType> {
   KotlinType({
     required this.flags,
     required this.kind,
@@ -1282,7 +1390,7 @@
       _$KotlinTypeFromJson(json);
 
   @override
-  R accept<R>(Visitor<KotlinType, R> v) {
+  R accept<R>(ElementVisitor<KotlinType, R> v) {
     return v.visit(this);
   }
 
@@ -1311,7 +1419,7 @@
 }
 
 @JsonSerializable(createToJson: false)
-class KotlinTypeParameter implements Element<KotlinTypeParameter> {
+final class KotlinTypeParameter with Element<KotlinTypeParameter> {
   KotlinTypeParameter({
     required this.name,
     required this.id,
@@ -1330,13 +1438,13 @@
       _$KotlinTypeParameterFromJson(json);
 
   @override
-  R accept<R>(Visitor<KotlinTypeParameter, R> v) {
+  R accept<R>(ElementVisitor<KotlinTypeParameter, R> v) {
     return v.visit(this);
   }
 }
 
 @JsonSerializable(createToJson: false)
-class KotlinValueParameter implements Element<KotlinValueParameter> {
+final class KotlinValueParameter with Element<KotlinValueParameter> {
   KotlinValueParameter({
     required this.name,
     required this.flags,
@@ -1353,12 +1461,12 @@
       _$KotlinValueParameterFromJson(json);
 
   @override
-  R accept<R>(Visitor<KotlinValueParameter, R> v) {
+  R accept<R>(ElementVisitor<KotlinValueParameter, R> v) {
     return v.visit(this);
   }
 }
 
-sealed class KotlinTypeArgument implements Element<KotlinTypeArgument> {
+sealed class KotlinTypeArgument with Element<KotlinTypeArgument> {
   KotlinTypeArgument();
 
   factory KotlinTypeArgument.fromJson(Map<String, dynamic> json) =>
@@ -1370,14 +1478,14 @@
             );
 
   @override
-  R accept<R>(Visitor<KotlinTypeArgument, R> v) {
+  R accept<R>(ElementVisitor<KotlinTypeArgument, R> v) {
     return v.visit(this);
   }
 }
 
-class KotlinWildcard extends KotlinTypeArgument {}
+final class KotlinWildcard extends KotlinTypeArgument {}
 
-class KotlinTypeProjection extends KotlinTypeArgument {
+final class KotlinTypeProjection extends KotlinTypeArgument {
   KotlinTypeProjection({required this.type, required this.variance});
 
   final KotlinType type;
diff --git a/pkgs/jnigen/lib/src/elements/elements.g.dart b/pkgs/jnigen/lib/src/elements/elements.g.dart
index 57ec0cc..b252101 100644
--- a/pkgs/jnigen/lib/src/elements/elements.g.dart
+++ b/pkgs/jnigen/lib/src/elements/elements.g.dart
@@ -143,6 +143,7 @@
           const {},
       name: json['name'] as String,
       type: ReferredType.fromJson(json['type'] as Map<String, dynamic>),
+      descriptor: json['descriptor'] as String?,
       defaultValue: json['defaultValue'],
     );
 
@@ -359,3 +360,11 @@
           : KotlinType.fromJson(
               json['varargElementType'] as Map<String, dynamic>),
     );
+
+const _$TypeKindEnumMap = {
+  TypeKind.primitive: 'PRIMITIVE',
+  TypeKind.typeVariable: 'TYPE_VARIABLE',
+  TypeKind.wildcard: 'WILDCARD',
+  TypeKind.declared: 'DECLARED',
+  TypeKind.array: 'ARRAY',
+};
diff --git a/pkgs/jnigen/lib/src/elements/j_elements.dart b/pkgs/jnigen/lib/src/elements/j_elements.dart
deleted file mode 100644
index 50fe889..0000000
--- a/pkgs/jnigen/lib/src/elements/j_elements.dart
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright (c) 2024, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'elements.dart' as ast;
-
-abstract class Element {
-  void accept(Visitor visitor);
-}
-
-abstract class Visitor {
-  void visitClass(ClassDecl c) {}
-  void visitMethod(Method method) {}
-  void visitField(Field field) {}
-  void visitParam(Param parameter) {}
-}
-
-class Classes implements Element {
-  Classes(this._classes);
-  final ast.Classes _classes;
-
-  @override
-  void accept(Visitor visitor) {
-    for (final value in _classes.decls.values) {
-      final classDecl = ClassDecl(value);
-      classDecl.accept(visitor);
-    }
-  }
-
-  void let(void Function(dynamic userClasses) param0) {}
-}
-
-class ClassDecl implements Element {
-  ClassDecl(this._classDecl);
-  final ast.ClassDecl _classDecl;
-
-  String get binaryName => _classDecl.binaryName;
-
-  bool get isExcluded => _classDecl.isExcluded;
-  set isExcluded(bool value) => _classDecl.isExcluded = value;
-
-  String get name => _classDecl.userDefinedName ?? _classDecl.name;
-  set name(String newName) => _classDecl.userDefinedName = newName;
-
-  String get originalName => _classDecl.name;
-
-  @override
-  void accept(Visitor visitor) {
-    visitor.visitClass(this);
-    if (_classDecl.isExcluded) return;
-    for (final method in _classDecl.methods) {
-      Method(method).accept(visitor);
-    }
-    for (var field in _classDecl.fields) {
-      Field(field).accept(visitor);
-    }
-  }
-}
-
-class Method implements Element {
-  Method(this._method);
-
-  final ast.Method _method;
-
-  bool get isExcluded => _method.userDefinedIsExcluded;
-  set isExcluded(bool value) => _method.userDefinedIsExcluded = value;
-
-  String get name => _method.userDefinedName ?? _method.name;
-  set name(String newName) => _method.userDefinedName = newName;
-
-  String get originalName => _method.name;
-
-  bool get isConstructor => _method.isConstructor;
-
-  @override
-  void accept(Visitor visitor) {
-    visitor.visitMethod(this);
-    if (_method.userDefinedIsExcluded) return;
-    for (final param in _method.params) {
-      Param(param).accept(visitor);
-    }
-  }
-}
-
-class Param implements Element {
-  Param(this._param);
-
-  final ast.Param _param;
-
-  String get name => _param.userDefinedName ?? _param.name;
-  set name(String newName) => _param.userDefinedName = newName;
-
-  String get originalName => _param.name;
-
-  @override
-  void accept(Visitor visitor) {
-    visitor.visitParam(this);
-  }
-}
-
-class Field implements Element {
-  Field(this._field);
-
-  final ast.Field _field;
-
-  bool get isExcluded => _field.isExcluded;
-  set isExcluded(bool value) => _field.isExcluded = value;
-
-  String get name => _field.userDefinedName ?? _field.name;
-  set name(String newName) => _field.userDefinedName = newName;
-
-  String get originalName => _field.name;
-
-  @override
-  void accept(Visitor visitor) {
-    visitor.visitField(this);
-  }
-}
diff --git a/pkgs/jnigen/lib/src/elements/stability_models.dart b/pkgs/jnigen/lib/src/elements/stability_models.dart
new file mode 100644
index 0000000..bd42bda
--- /dev/null
+++ b/pkgs/jnigen/lib/src/elements/stability_models.dart
@@ -0,0 +1,266 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:json_annotation/json_annotation.dart';
+import 'package:pub_semver/pub_semver.dart';
+
+part 'stability_models.g.dart';
+
+String _versionToString(Version v) => v.toString();
+
+@JsonSerializable()
+final class StabilityInfo {
+  @JsonKey(fromJson: Version.parse, toJson: _versionToString)
+  final Version formatVersion;
+  final String packageName;
+  final Map<String, StabilityFile> files;
+
+  StabilityInfo({
+    required this.formatVersion,
+    required this.packageName,
+    required this.files,
+  });
+
+  factory StabilityInfo.fromJson(Map<String, dynamic> json) =>
+      _$StabilityInfoFromJson(json);
+
+  Map<String, dynamic> toJson() => _$StabilityInfoToJson(this);
+}
+
+@JsonSerializable()
+final class StabilityFile {
+  final Map<String, StabilityClass> classes;
+
+  StabilityFile({required this.classes});
+
+  factory StabilityFile.fromJson(Map<String, dynamic> json) =>
+      _$StabilityFileFromJson(json);
+
+  Map<String, dynamic> toJson() => _$StabilityFileToJson(this);
+}
+
+@JsonSerializable()
+final class StabilityClass {
+  final String name;
+  final StabilityType superClass;
+  final List<StabilityType> superInterfaces;
+  final Map<String, StabilityField> fields;
+  final Map<String, StabilityMethod> methods;
+  final List<StabilityTypeParameter> typeParameters;
+
+  StabilityClass({
+    required this.name,
+    required this.superClass,
+    required this.superInterfaces,
+    required this.fields,
+    required this.methods,
+    required this.typeParameters,
+  });
+
+  factory StabilityClass.fromJson(Map<String, dynamic> json) =>
+      _$StabilityClassFromJson(json);
+
+  Map<String, dynamic> toJson() => _$StabilityClassToJson(this);
+}
+
+@JsonSerializable()
+final class StabilityField {
+  final String name;
+  final StabilityType type;
+
+  StabilityField({required this.name, required this.type});
+
+  factory StabilityField.fromJson(Map<String, dynamic> json) =>
+      _$StabilityFieldFromJson(json);
+
+  Map<String, dynamic> toJson() => _$StabilityFieldToJson(this);
+}
+
+@JsonSerializable()
+final class StabilityMethod {
+  final String name;
+  final List<StabilityTypeParameter> typeParameters;
+  final List<StabilityMethodParameter> methodParameters;
+  final StabilityType returnType;
+
+  StabilityMethod({
+    required this.name,
+    required this.typeParameters,
+    required this.methodParameters,
+    required this.returnType,
+  });
+
+  factory StabilityMethod.fromJson(Map<String, dynamic> json) =>
+      _$StabilityMethodFromJson(json);
+
+  Map<String, dynamic> toJson() => _$StabilityMethodToJson(this);
+}
+
+@JsonSerializable()
+final class StabilityMethodParameter {
+  final String name;
+  final StabilityType type;
+
+  StabilityMethodParameter({required this.name, required this.type});
+
+  factory StabilityMethodParameter.fromJson(Map<String, dynamic> json) =>
+      _$StabilityMethodParameterFromJson(json);
+
+  Map<String, dynamic> toJson() => _$StabilityMethodParameterToJson(this);
+}
+
+@JsonSerializable()
+final class StabilityTypeParameter {
+  final String name;
+  final List<StabilityType> bounds;
+
+  StabilityTypeParameter({required this.name, required this.bounds});
+
+  factory StabilityTypeParameter.fromJson(Map<String, dynamic> json) =>
+      _$StabilityTypeParameterFromJson(json);
+
+  Map<String, dynamic> toJson() => _$StabilityTypeParameterToJson(this);
+}
+
+@JsonEnum(alwaysCreate: true)
+enum StabilityTypeKind {
+  primitive,
+  typeVariable,
+  wildcard,
+  declared,
+  array,
+}
+
+@JsonEnum(alwaysCreate: true)
+enum Nullability {
+  /// The type is explicitly non-nullable.
+  nonNullable,
+
+  /// The type is explicitly nullable.
+  nullable,
+
+  /// The nullability is unspecified.
+  platform,
+}
+
+sealed class StabilityType {
+  // Since json_serializable doesn't directly support union types,
+  // we have to temporarily store `type` in a JSON map, and switch on the
+  // enum value received.
+  factory StabilityType.fromJson(Map<String, dynamic> json) {
+    final kind = $enumDecode(_$StabilityTypeKindEnumMap, json['kind']);
+    final typeJson = json['type'] as Map<String, dynamic>;
+    switch (kind) {
+      case StabilityTypeKind.primitive:
+        return StabilityPrimitiveType.fromJson(typeJson);
+      case StabilityTypeKind.typeVariable:
+        return StabilityTypeVariable.fromJson(typeJson);
+      case StabilityTypeKind.wildcard:
+        return StabilityWildcard.fromJson(typeJson);
+      case StabilityTypeKind.declared:
+        return StabilityDeclaredType.fromJson(typeJson);
+      case StabilityTypeKind.array:
+        return StabilityArrayType.fromJson(typeJson);
+    }
+  }
+
+  Map<String, dynamic> toJson();
+}
+
+@JsonSerializable()
+final class StabilityPrimitiveType implements StabilityType {
+  final String name;
+
+  StabilityPrimitiveType({required this.name});
+
+  factory StabilityPrimitiveType.fromJson(Map<String, dynamic> json) =>
+      _$StabilityPrimitiveTypeFromJson(json);
+
+  @override
+  Map<String, dynamic> toJson() => {
+        'kind': _$StabilityTypeKindEnumMap[StabilityTypeKind.primitive],
+        'type': _$StabilityPrimitiveTypeToJson(this)
+      };
+}
+
+@JsonSerializable()
+final class StabilityTypeVariable implements StabilityType {
+  final String name;
+  final Nullability nullability;
+
+  StabilityTypeVariable({required this.name, required this.nullability});
+
+  factory StabilityTypeVariable.fromJson(Map<String, dynamic> json) =>
+      _$StabilityTypeVariableFromJson(json);
+
+  @override
+  Map<String, dynamic> toJson() => {
+        'kind': _$StabilityTypeKindEnumMap[StabilityTypeKind.typeVariable],
+        'type': _$StabilityTypeVariableToJson(this)
+      };
+}
+
+@JsonSerializable()
+final class StabilityWildcard implements StabilityType {
+  final StabilityType? extendsBound;
+  final StabilityType? superBound;
+  final Nullability nullability;
+
+  StabilityWildcard({
+    this.extendsBound,
+    this.superBound,
+    required this.nullability,
+  });
+
+  factory StabilityWildcard.fromJson(Map<String, dynamic> json) =>
+      _$StabilityWildcardFromJson(json);
+
+  @override
+  Map<String, dynamic> toJson() => {
+        'kind': _$StabilityTypeKindEnumMap[StabilityTypeKind.wildcard],
+        'type': _$StabilityWildcardToJson(this)
+      };
+}
+
+@JsonSerializable()
+final class StabilityDeclaredType implements StabilityType {
+  final String binaryName;
+  final List<StabilityType> typeArguments;
+  final Nullability nullability;
+
+  StabilityDeclaredType({
+    required this.binaryName,
+    required this.typeArguments,
+    required this.nullability,
+  });
+
+  factory StabilityDeclaredType.fromJson(Map<String, dynamic> json) =>
+      _$StabilityDeclaredTypeFromJson(json);
+
+  @override
+  Map<String, dynamic> toJson() => {
+        'kind': _$StabilityTypeKindEnumMap[StabilityTypeKind.declared],
+        'type': _$StabilityDeclaredTypeToJson(this)
+      };
+}
+
+@JsonSerializable()
+final class StabilityArrayType implements StabilityType {
+  final StabilityType elementType;
+  final Nullability nullability;
+
+  StabilityArrayType({
+    required this.elementType,
+    required this.nullability,
+  });
+
+  factory StabilityArrayType.fromJson(Map<String, dynamic> json) =>
+      _$StabilityArrayTypeFromJson(json);
+
+  @override
+  Map<String, dynamic> toJson() => {
+        'kind': _$StabilityTypeKindEnumMap[StabilityTypeKind.declared],
+        'type': _$StabilityArrayTypeToJson(this)
+      };
+}
diff --git a/pkgs/jnigen/lib/src/elements/stability_models.g.dart b/pkgs/jnigen/lib/src/elements/stability_models.g.dart
new file mode 100644
index 0000000..3f144a0
--- /dev/null
+++ b/pkgs/jnigen/lib/src/elements/stability_models.g.dart
@@ -0,0 +1,224 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'stability_models.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+StabilityInfo _$StabilityInfoFromJson(Map<String, dynamic> json) =>
+    StabilityInfo(
+      formatVersion: Version.parse(json['formatVersion'] as String),
+      packageName: json['packageName'] as String,
+      files: (json['files'] as Map<String, dynamic>).map(
+        (k, e) =>
+            MapEntry(k, StabilityFile.fromJson(e as Map<String, dynamic>)),
+      ),
+    );
+
+Map<String, dynamic> _$StabilityInfoToJson(StabilityInfo instance) =>
+    <String, dynamic>{
+      'formatVersion': _versionToString(instance.formatVersion),
+      'packageName': instance.packageName,
+      'files': instance.files,
+    };
+
+StabilityFile _$StabilityFileFromJson(Map<String, dynamic> json) =>
+    StabilityFile(
+      classes: (json['classes'] as Map<String, dynamic>).map(
+        (k, e) =>
+            MapEntry(k, StabilityClass.fromJson(e as Map<String, dynamic>)),
+      ),
+    );
+
+Map<String, dynamic> _$StabilityFileToJson(StabilityFile instance) =>
+    <String, dynamic>{
+      'classes': instance.classes,
+    };
+
+StabilityClass _$StabilityClassFromJson(Map<String, dynamic> json) =>
+    StabilityClass(
+      name: json['name'] as String,
+      superClass:
+          StabilityType.fromJson(json['superClass'] as Map<String, dynamic>),
+      superInterfaces: (json['superInterfaces'] as List<dynamic>)
+          .map((e) => StabilityType.fromJson(e as Map<String, dynamic>))
+          .toList(),
+      fields: (json['fields'] as Map<String, dynamic>).map(
+        (k, e) =>
+            MapEntry(k, StabilityField.fromJson(e as Map<String, dynamic>)),
+      ),
+      methods: (json['methods'] as Map<String, dynamic>).map(
+        (k, e) =>
+            MapEntry(k, StabilityMethod.fromJson(e as Map<String, dynamic>)),
+      ),
+      typeParameters: (json['typeParameters'] as List<dynamic>)
+          .map(
+              (e) => StabilityTypeParameter.fromJson(e as Map<String, dynamic>))
+          .toList(),
+    );
+
+Map<String, dynamic> _$StabilityClassToJson(StabilityClass instance) =>
+    <String, dynamic>{
+      'name': instance.name,
+      'superClass': instance.superClass,
+      'superInterfaces': instance.superInterfaces,
+      'fields': instance.fields,
+      'methods': instance.methods,
+      'typeParameters': instance.typeParameters,
+    };
+
+StabilityField _$StabilityFieldFromJson(Map<String, dynamic> json) =>
+    StabilityField(
+      name: json['name'] as String,
+      type: StabilityType.fromJson(json['type'] as Map<String, dynamic>),
+    );
+
+Map<String, dynamic> _$StabilityFieldToJson(StabilityField instance) =>
+    <String, dynamic>{
+      'name': instance.name,
+      'type': instance.type,
+    };
+
+StabilityMethod _$StabilityMethodFromJson(Map<String, dynamic> json) =>
+    StabilityMethod(
+      name: json['name'] as String,
+      typeParameters: (json['typeParameters'] as List<dynamic>)
+          .map(
+              (e) => StabilityTypeParameter.fromJson(e as Map<String, dynamic>))
+          .toList(),
+      methodParameters: (json['methodParameters'] as List<dynamic>)
+          .map((e) =>
+              StabilityMethodParameter.fromJson(e as Map<String, dynamic>))
+          .toList(),
+      returnType:
+          StabilityType.fromJson(json['returnType'] as Map<String, dynamic>),
+    );
+
+Map<String, dynamic> _$StabilityMethodToJson(StabilityMethod instance) =>
+    <String, dynamic>{
+      'name': instance.name,
+      'typeParameters': instance.typeParameters,
+      'methodParameters': instance.methodParameters,
+      'returnType': instance.returnType,
+    };
+
+StabilityMethodParameter _$StabilityMethodParameterFromJson(
+        Map<String, dynamic> json) =>
+    StabilityMethodParameter(
+      name: json['name'] as String,
+      type: StabilityType.fromJson(json['type'] as Map<String, dynamic>),
+    );
+
+Map<String, dynamic> _$StabilityMethodParameterToJson(
+        StabilityMethodParameter instance) =>
+    <String, dynamic>{
+      'name': instance.name,
+      'type': instance.type,
+    };
+
+StabilityTypeParameter _$StabilityTypeParameterFromJson(
+        Map<String, dynamic> json) =>
+    StabilityTypeParameter(
+      name: json['name'] as String,
+      bounds: (json['bounds'] as List<dynamic>)
+          .map((e) => StabilityType.fromJson(e as Map<String, dynamic>))
+          .toList(),
+    );
+
+Map<String, dynamic> _$StabilityTypeParameterToJson(
+        StabilityTypeParameter instance) =>
+    <String, dynamic>{
+      'name': instance.name,
+      'bounds': instance.bounds,
+    };
+
+StabilityPrimitiveType _$StabilityPrimitiveTypeFromJson(
+        Map<String, dynamic> json) =>
+    StabilityPrimitiveType(
+      name: json['name'] as String,
+    );
+
+Map<String, dynamic> _$StabilityPrimitiveTypeToJson(
+        StabilityPrimitiveType instance) =>
+    <String, dynamic>{
+      'name': instance.name,
+    };
+
+StabilityTypeVariable _$StabilityTypeVariableFromJson(
+        Map<String, dynamic> json) =>
+    StabilityTypeVariable(
+      name: json['name'] as String,
+      nullability: $enumDecode(_$NullabilityEnumMap, json['nullability']),
+    );
+
+Map<String, dynamic> _$StabilityTypeVariableToJson(
+        StabilityTypeVariable instance) =>
+    <String, dynamic>{
+      'name': instance.name,
+      'nullability': _$NullabilityEnumMap[instance.nullability]!,
+    };
+
+const _$NullabilityEnumMap = {
+  Nullability.nonNullable: 'nonNullable',
+  Nullability.nullable: 'nullable',
+  Nullability.platform: 'platform',
+};
+
+StabilityWildcard _$StabilityWildcardFromJson(Map<String, dynamic> json) =>
+    StabilityWildcard(
+      extendsBound: json['extendsBound'] == null
+          ? null
+          : StabilityType.fromJson(
+              json['extendsBound'] as Map<String, dynamic>),
+      superBound: json['superBound'] == null
+          ? null
+          : StabilityType.fromJson(json['superBound'] as Map<String, dynamic>),
+      nullability: $enumDecode(_$NullabilityEnumMap, json['nullability']),
+    );
+
+Map<String, dynamic> _$StabilityWildcardToJson(StabilityWildcard instance) =>
+    <String, dynamic>{
+      'extendsBound': instance.extendsBound,
+      'superBound': instance.superBound,
+      'nullability': _$NullabilityEnumMap[instance.nullability]!,
+    };
+
+StabilityDeclaredType _$StabilityDeclaredTypeFromJson(
+        Map<String, dynamic> json) =>
+    StabilityDeclaredType(
+      binaryName: json['binaryName'] as String,
+      typeArguments: (json['typeArguments'] as List<dynamic>)
+          .map((e) => StabilityType.fromJson(e as Map<String, dynamic>))
+          .toList(),
+      nullability: $enumDecode(_$NullabilityEnumMap, json['nullability']),
+    );
+
+Map<String, dynamic> _$StabilityDeclaredTypeToJson(
+        StabilityDeclaredType instance) =>
+    <String, dynamic>{
+      'binaryName': instance.binaryName,
+      'typeArguments': instance.typeArguments,
+      'nullability': _$NullabilityEnumMap[instance.nullability]!,
+    };
+
+StabilityArrayType _$StabilityArrayTypeFromJson(Map<String, dynamic> json) =>
+    StabilityArrayType(
+      elementType:
+          StabilityType.fromJson(json['elementType'] as Map<String, dynamic>),
+      nullability: $enumDecode(_$NullabilityEnumMap, json['nullability']),
+    );
+
+Map<String, dynamic> _$StabilityArrayTypeToJson(StabilityArrayType instance) =>
+    <String, dynamic>{
+      'elementType': instance.elementType,
+      'nullability': _$NullabilityEnumMap[instance.nullability]!,
+    };
+
+const _$StabilityTypeKindEnumMap = {
+  StabilityTypeKind.primitive: 'primitive',
+  StabilityTypeKind.typeVariable: 'typeVariable',
+  StabilityTypeKind.wildcard: 'wildcard',
+  StabilityTypeKind.declared: 'declared',
+  StabilityTypeKind.array: 'array',
+};
diff --git a/pkgs/jnigen/lib/src/generate_bindings.dart b/pkgs/jnigen/lib/src/generate_bindings.dart
index d49c847..01da43a 100644
--- a/pkgs/jnigen/lib/src/generate_bindings.dart
+++ b/pkgs/jnigen/lib/src/generate_bindings.dart
@@ -4,20 +4,21 @@
 
 import 'dart:async';
 import 'dart:convert';
-import 'dart:io';
 
 import 'bindings/dart_generator.dart';
-import 'bindings/excluder.dart';
+import 'bindings/exporter.dart';
+import 'bindings/graph_builder.dart';
+import 'bindings/importer.dart';
 import 'bindings/kotlin_processor.dart';
 import 'bindings/linker.dart';
-import 'bindings/renamer.dart';
 import 'bindings/visitor.dart';
 import 'config/config.dart';
 import 'elements/elements.dart';
-import 'elements/j_elements.dart' as j_ast;
 import 'logging/logging.dart';
 import 'summary/summary.dart';
 import 'tools/tools.dart';
+import 'transformers/default_renamer.dart';
+import 'transformers/graph.dart';
 
 void collectOutputStream(Stream<List<int>> stream, StringBuffer buffer) =>
     stream.transform(const Utf8Decoder()).forEach(buffer.write);
@@ -40,28 +41,28 @@
     log.fatal(e.message);
   }
 
-  final userClasses = j_ast.Classes(classes);
-  config.visitors?.forEach(userClasses.accept);
-
   // Keep the order in sync with `elements/elements.dart`.
-  var stage = GenerationStage.userVisitors;
+  var stage = GenerationStage.unprocessed;
   R runStage<R>(TopLevelVisitor<R> visitor) {
     assert(visitor.stage.index == stage.index + 1);
     stage = visitor.stage;
     return classes.accept(visitor);
   }
 
-  runStage(Excluder(config));
-  runStage(KotlinProcessor());
-  await runStage(Linker(config));
-  runStage(Renamer(config));
-  // classes.accept(const Printer());
-
-  try {
-    await classes.accept(DartGenerator(config));
-    log.info('Completed');
-  } on Exception catch (e, trace) {
-    stderr.writeln(trace);
-    log.fatal('Error while writing bindings: $e');
+  void runUserTransformersStage(Bindings bindings) {
+    assert(GenerationStage.userTransformers.index == stage.index + 1);
+    stage = GenerationStage.userTransformers;
+    config.visitors?.forEach(bindings.accept);
+    // FIXME
+    bindings.accept(DefaultRenamer(config));
   }
+
+  runStage(KotlinProcessor());
+  await runStage(Importer(config));
+  await runStage(Linker(config));
+  final bindings = runStage(GraphBuilder(config));
+  runUserTransformersStage(bindings);
+  await runStage(Exporter(config));
+  await runStage(DartGenerator(config));
+  // classes.accept(const Printer());
 }
diff --git a/pkgs/jnigen/lib/src/transformers/default_excluder.dart b/pkgs/jnigen/lib/src/transformers/default_excluder.dart
new file mode 100644
index 0000000..e992f04
--- /dev/null
+++ b/pkgs/jnigen/lib/src/transformers/default_excluder.dart
@@ -0,0 +1,95 @@
+// // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// // for details. All rights reserved. Use of this source code is governed by a
+// // BSD-style license that can be found in the LICENSE file.
+
+// import '../config/config.dart';
+// import '../elements/elements.dart';
+// import '../logging/logging.dart';
+// import 'visitor.dart';
+
+// extension on HasModifiers {
+//   bool get isPrivate => !isPublic;
+// }
+
+// // TODO(https://github.com/dart-lang/native/issues/1164): Kotlin compiler
+// // appends the method name with a dash and a hash code when arguments contain
+// // inline classes. This is because inline classes do not have any runtime type
+// // and the typical operator overloading supported by JVM cannot work for them.
+// //
+// // Once we support inline classes, we can relax the following constraints.
+// final _validDartIdentifier = RegExp(r'^[a-zA-Z_$][a-zA-Z0-9_$]*$');
+
+// extension on String {
+//   bool get isInvalidDartIdentifier =>
+//       !_validDartIdentifier.hasMatch(this) &&
+//       this != '<init>' &&
+//       this != '<clinit>';
+// }
+
+// class Excluder extends ElementVisitor<Classes, void> with TopLevelVisitor {
+//   @override
+//   final stage = GenerationStage.excluder;
+
+//   final Config config;
+
+//   const Excluder(this.config);
+
+//   @override
+//   void visit(Classes node) {
+//     node.decls.removeWhere((_, classDecl) {
+//       final excluded = classDecl.isPrivate || classDecl.isExcluded;
+//       if (excluded) {
+//         log.fine('Excluded class ${classDecl.binaryName}');
+//       }
+//       if (classDecl.name.isInvalidDartIdentifier) {
+//         log.warning('Excluded class ${classDecl.binaryName}: the name is not a'
+//             ' valid Dart identifer');
+//         return true;
+//       }
+//       return excluded;
+//     });
+//     final classExcluder = _ClassExcluder(config);
+//     for (final classDecl in node.decls.values) {
+//       classDecl.accept(classExcluder);
+//     }
+//   }
+// }
+
+// class _ClassExcluder extends ElementVisitor<ClassDecl, void> {
+//   final Config config;
+
+//   _ClassExcluder(this.config);
+
+//   @override
+//   void visit(ClassDecl node) {
+//     node.methods = node.methods.where((method) {
+//       final isPrivate = method.isPrivate;
+//       final isAbstractCtor = method.isConstructor && node.isAbstract;
+//       final isBridgeMethod = method.isSynthetic && method.isBridge;
+//       final excluded = isPrivate || isAbstractCtor || isBridgeMethod;
+//       if (excluded) {
+//         log.fine('Excluded method ${node.binaryName}#${method.name}');
+//       }
+//       if (method.name.isInvalidDartIdentifier) {
+//         log.warning(
+//             'Excluded method ${node.binaryName}#${method.name}: the name is not'
+//             ' a valid Dart identifer');
+//         return false;
+//       }
+//       return !excluded;
+//     }).toList();
+//     node.fields = node.fields.where((field) {
+//       final excluded = field.isExcluded || field.isPrivate;
+//       if (excluded) {
+//         log.fine('Excluded field ${node.binaryName}#${field.name}');
+//       }
+//       if (field.name.isInvalidDartIdentifier) {
+//         log.warning(
+//             'Excluded field ${node.binaryName}#${field.name}: the name is not'
+//             ' a valid Dart identifer');
+//         return false;
+//       }
+//       return !excluded;
+//     }).toList();
+//   }
+// }
diff --git a/pkgs/jnigen/lib/src/transformers/default_renamer.dart b/pkgs/jnigen/lib/src/transformers/default_renamer.dart
new file mode 100644
index 0000000..fe5b7ff
--- /dev/null
+++ b/pkgs/jnigen/lib/src/transformers/default_renamer.dart
@@ -0,0 +1,158 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../config/config.dart';
+import '../logging/logging.dart';
+import 'graph.dart';
+
+final class DefaultRenamer extends Visitor {
+  final Config config;
+
+  DefaultRenamer(this.config);
+
+  final _nodeToUsedNames = <Object, Set<String>>{};
+  final _validDartIdentifierCharacters = RegExp(r'[a-zA-Z0-9_$]');
+
+  String _preprocess(String name) {
+    // Replaces the `_` prefix with `$_` to prevent hiding public members.
+    String makePublic(String name) =>
+        name.startsWith('_') ? '\$_${name.substring(1)}' : name;
+
+    // Replaces each dollar sign with two dollar signs in [name].
+    // For example `$foo$$bar$` -> `$$foo$$$$bar$$`.
+    String doubleDollarSigns(String name) => name.replaceAll(r'$', r'$$');
+
+    // Replaces each disallowed characters with an underscore.
+    String removeDisallowedChars(String name) {
+      final newName = StringBuffer();
+      for (var i = 0; i < name.length; ++i) {
+        final char = name[i];
+        if (_validDartIdentifierCharacters.hasMatch(char)) {
+          newName.write(char);
+        } else {
+          newName.write('_');
+        }
+      }
+      return newName.toString();
+    }
+
+    return makePublic(doubleDollarSigns(removeDisallowedChars(name)));
+  }
+
+  final _countRegexp = RegExp(r'^(.*)\$(\d+)?$');
+
+  Set<String> _usedNamesIn(Object node) {
+    return _nodeToUsedNames[node] ??= {};
+  }
+
+  // FIXME: return string, get a bool function for isNameAllowed.
+  void _renameConflict(dynamic renamable, Object parent) {
+    final usedNames = _usedNamesIn(parent);
+    // ignore: avoid_dynamic_calls - Using dynamic as `_Renamable` is private.
+    var name = renamable.name as String;
+    // ignore: avoid_dynamic_calls
+    if (!(renamable.isNameAllowed(name) as bool)) {
+      // Try appending a dollar sign if the name is a Dart keyword or a
+      // disallowed identifier.
+      name = '$name\$';
+    }
+    final regexMatch = _countRegexp.firstMatch(name);
+    final String namePart;
+    int countPart;
+    if (regexMatch != null) {
+      namePart = regexMatch[1]!;
+      countPart = int.parse(regexMatch[2] ?? '0');
+    } else {
+      namePart = name;
+      countPart = 0;
+    }
+    while (usedNames.contains(name)) {
+      countPart += 1;
+      name = '$namePart\$$countPart';
+    }
+    // ignore: avoid_dynamic_calls
+    renamable.name = name;
+    usedNames.add(name);
+  }
+
+  @override
+  void visitClass(Class cls) {
+    if (cls.stableName case final stableName?) {
+      cls.name = stableName;
+      log.finest('Used the stable name "$stableName" for class "$cls".');
+      _usedNamesIn(cls.enclosingFile).add(cls.name!);
+    } else {
+      cls.name = _preprocess(cls.originalName);
+      if (cls.enclosingClass != null) {
+        cls.name = '${cls.enclosingClass!.name}\$${cls.name}';
+      }
+      _renameConflict(cls, cls.enclosingFile);
+    }
+    for (final property in cls.properties) {
+      if (property.name != null) {
+        _usedNamesIn(cls).add(property.name!);
+      } else if (property.stableName case final stableName?) {
+        property.name = stableName;
+        log.finest(
+            'Used the stable name "$stableName" for property "$property" of '
+            'class "${property.enclosingClass}".');
+        _usedNamesIn(cls).add(property.name!);
+      }
+    }
+    for (final method in cls.methods) {
+      if (method.name != null) {
+        _usedNamesIn(cls).add(method.name!);
+      } else if (method.stableName case final stableName?) {
+        method.name = stableName;
+        log.finest('Used the stable name "$stableName" for method "$method" of '
+            'class "${method.enclosingClass}".');
+        _usedNamesIn(cls).add(method.name!);
+      }
+    }
+    super.visitClass(cls);
+  }
+
+  @override
+  void visitProperty(Property property) {
+    final parent = property.enclosingClass.isTopLevel
+        ? property.enclosingClass.enclosingFile
+        : property.enclosingClass;
+    if (property.name != null) {
+      return;
+    }
+    property.name = _preprocess(property.originalName);
+    _renameConflict(property, parent);
+  }
+
+  @override
+  void visitMethod(Method method) {
+    final parent = method.enclosingClass.isTopLevel
+        ? method.enclosingClass.enclosingFile
+        : method.enclosingClass;
+    if (method.name != null) {
+      return super.visitMethod(method);
+    }
+    method.name = _preprocess(method.originalName);
+    _renameConflict(method, parent);
+    final b = method.enclosingClass.identifier ==
+        'com.github.dart_lang.jnigen.inheritance.DerivedInterface';
+    if (b) log.warning('method $method is named ${method.name}');
+    super.visitMethod(method);
+  }
+
+  @override
+  void visitMethodParameter(MethodParameter methodParameter) {
+    if (methodParameter.stableName case final stableName?) {
+      methodParameter.name = stableName;
+      log.finest('Used the stable name "$stableName" for method parameter '
+          'at index ${methodParameter.identifier} of method '
+          '"${methodParameter.enclosingMethod}" of '
+          'class "${methodParameter.enclosingMethod.enclosingClass}"');
+      _usedNamesIn(methodParameter.enclosingMethod).add(methodParameter.name!);
+    } else {
+      methodParameter.name = _preprocess(methodParameter.originalName);
+      _renameConflict(methodParameter, methodParameter.enclosingMethod);
+    }
+  }
+}
diff --git a/pkgs/jnigen/lib/src/transformers/graph.dart b/pkgs/jnigen/lib/src/transformers/graph.dart
new file mode 100644
index 0000000..7a48c8a
--- /dev/null
+++ b/pkgs/jnigen/lib/src/transformers/graph.dart
@@ -0,0 +1,420 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection';
+
+import 'package:meta/meta.dart' as meta show internal;
+
+import '../elements/elements.dart' as internal;
+
+const _disallowedAsClassName = {
+  'abstract',
+  'covariant',
+  'deferred',
+  'dynamic',
+  'export',
+  'extension',
+  'external',
+  'factory',
+  'Function',
+  'implements',
+  'interface',
+  'late',
+  'library',
+  'mixin',
+  'operator',
+  'part',
+  'required',
+  'static',
+  'typedef',
+};
+
+const _keywords = {
+  'assert',
+  'await', // Cannot be used in async context.
+  'break',
+  'case',
+  'catch',
+  'class',
+  'const',
+  'continue',
+  'default',
+  'do',
+  'else',
+  'enum',
+  'extends',
+  'false',
+  'final',
+  'finally',
+  'for',
+  'if',
+  'import',
+  'in',
+  'is',
+  'new',
+  'null',
+  'rethrow',
+  'return',
+  'super',
+  'switch',
+  'this',
+  'throw',
+  'true',
+  'try',
+  'var',
+  'void',
+  'while',
+  'with',
+  'yield', // Cannot be used in async context.
+};
+
+const _disallowedInInterface = {
+  'implement',
+  'implementIn',
+};
+
+final _validDartIdentifier = RegExp(r'^[a-zA-Z_$][a-zA-Z0-9_$]*$');
+
+abstract class Visitor {
+  void visit(Bindings bindings) {
+    bindings.visitChildren(this);
+  }
+
+  void visitClass(Class cls) {
+    cls.visitChildren(this);
+  }
+
+  void visitProperty(Property property) {}
+
+  void visitMethod(Method method) {
+    method.visitChildren(this);
+  }
+
+  void visitMethodParameter(MethodParameter methodParameter) {}
+}
+
+abstract final class _Node<T extends internal.Element<T>> {
+  final T _internalNode;
+
+  _Node(this._internalNode);
+}
+
+base mixin _Visitable {
+  void accept(Visitor visitor);
+}
+
+base mixin _HasVisitableChildren {
+  void visitChildren(Visitor visitor);
+}
+
+base mixin _HasModifiers<T extends internal.HasModifiers<T>> on _Node<T> {
+  bool get isAbstract => _internalNode.isAbstract;
+  bool get isStatic => _internalNode.isStatic;
+  bool get isFinal => _internalNode.isFinal;
+  bool get isPublic => _internalNode.isPublic;
+  bool get isProtected => _internalNode.isProtected;
+  bool get isSynthetic => _internalNode.isSynthetic;
+  bool get isBridge => _internalNode.isBridge;
+}
+
+base mixin _Renamable<T extends internal.Renamable<T>> on _Node<T> {
+  /// The name that will uniquely identify this element between in the context
+  /// of its parent node.
+  String get identifier;
+
+  /// The original name of the element in the source language.
+  String get originalName => _internalNode.originalName;
+
+  /// The name loaded from the API stability file.
+  ///
+  /// This will be `null` if the element was not found in the API stability
+  /// file, for example, when running for the first time or after a new element
+  /// is added.
+  String? get stableName => _internalNode.stableName;
+
+  /// The current name of the element. This will be used in the generated
+  /// bindings.
+  ///
+  /// Setting is subject to validation.
+  String? get name => _internalNode.finalName;
+
+  set name(String? newName) {
+    _internalNode.finalName = newName;
+  }
+
+  /// Whether the given name is allowed for this element.
+  ///
+  /// Returns `false` if the name is a Dart keyword or cannot be syntactically
+  /// the name of this element due to name collision.
+  bool isNameAllowed(String name);
+}
+
+base mixin _Excludable<T extends internal.Excludable<T>> on _Node<T> {
+  /// Whether this element is excluded from the generated bindings.
+  bool get isExcluded => _internalNode.isExcluded;
+
+  set isExcluded(bool isExcluded) {
+    _internalNode.isExcluded = isExcluded;
+  }
+}
+
+/// This class represents the entire set of generated code for a single
+/// JNIgen run. It's the main entry point for any user-defined transformations.
+final class Bindings extends _Node<internal.Classes>
+    with _Visitable, _HasVisitableChildren {
+  @meta.internal
+  Bindings(super._internalNode, this._classes, this._files);
+
+  /// Stored in topological order of the classes.
+  final Map<String, Class> _classes;
+  final Map<String, DartFile> _files;
+
+  Iterable<Class> get classes => _classes.values;
+  Iterable<DartFile> get files => _files.values;
+
+  @override
+  void accept(Visitor visitor) {
+    visitor.visit(this);
+  }
+
+  @override
+  void visitChildren(Visitor visitor) {
+    for (final cls in classes) {
+      cls.accept(visitor);
+    }
+  }
+}
+
+/// Represents a Dart file.
+final class DartFile extends _Node<internal.DartFile>
+    with _HasVisitableChildren {
+  final Map<String, Class> _classes;
+
+  @meta.internal
+  DartFile(super._internalNode, this._classes) {
+    for (final cls in classes) {
+      cls.enclosingFile = this;
+    }
+  }
+
+  String get path => _internalNode.path;
+
+  Iterable<Class> get classes => _classes.values;
+
+  @override
+  void visitChildren(Visitor visitor) {
+    for (final cls in classes) {
+      cls.accept(visitor);
+    }
+  }
+}
+
+enum Language {
+  java,
+  kotlin,
+}
+
+enum DeclKind {
+  /// Declared as a normal class.
+  classKind,
+
+  /// Declared as an interface.
+  interfaceKind,
+
+  /// Declared as an enum.
+  enumKind,
+
+  /// Declared as a collection of top-level methods and properties.
+  packageKind,
+}
+
+/// Represents a Dart class or a collection of top-level methods and properties.
+final class Class extends _Node<internal.ClassDecl>
+    with
+        _Visitable,
+        _HasVisitableChildren,
+        _Renamable,
+        _Excludable,
+        _HasModifiers {
+  @meta.internal
+  Class(super._internalNode, this._properties, this._methods) {
+    for (final property in _properties.values) {
+      property.enclosingClass = this;
+    }
+    for (final method in _methods.values) {
+      method.enclosingClass = this;
+    }
+  }
+
+  /// The [DartFile] that this class is a part of.
+  late final DartFile enclosingFile;
+
+  /// The outer class of this class or `null` if this class is not nested.
+  late final Class? enclosingClass;
+
+  /// Map from name to field.
+  ///
+  /// The entries are ordered the same way as [internal.ClassDecl.fields].
+  final Map<String, Property> _properties;
+
+  /// Map from (name + signature) to method.
+  ///
+  /// The entries are ordered the same way as [internal.ClassDecl.methods].
+  final Map<String, Method> _methods;
+
+  Iterable<Property> get properties => _properties.values;
+  Iterable<Method> get methods => _methods.values;
+
+  /// The programming language of origin.
+  Language get language {
+    return _internalNode.kotlinClass != null ||
+            _internalNode.kotlinPackage != null
+        ? Language.kotlin
+        : Language.java;
+  }
+
+  /// The original declaration type of this class.
+  DeclKind get kind {
+    if (_internalNode.kotlinPackage != null) return DeclKind.packageKind;
+    return switch (_internalNode.declKind) {
+      internal.DeclKind.classKind => DeclKind.classKind,
+      internal.DeclKind.interfaceKind => DeclKind.interfaceKind,
+      internal.DeclKind.enumKind => DeclKind.enumKind,
+    };
+  }
+
+  /// Whether the class is actually only a number of top-level functions
+  /// and properties.
+  bool get isTopLevel => _internalNode.isTopLevel;
+
+  set isTopLevel(bool isTopLevel) {
+    _internalNode.isTopLevel = isTopLevel;
+  }
+
+  @override
+  void accept(Visitor visitor) {
+    visitor.visitClass(this);
+  }
+
+  @override
+  void visitChildren(Visitor visitor) {
+    for (final method in methods) {
+      method.accept(visitor);
+    }
+    for (final property in properties) {
+      property.accept(visitor);
+    }
+  }
+
+  @override
+  bool isNameAllowed(String name) {
+    return _validDartIdentifier.hasMatch(name) &&
+        !_disallowedAsClassName.contains(name) &&
+        !_keywords.contains(name);
+  }
+
+  @override
+  String get identifier => _internalNode.binaryName;
+
+  @override
+  String toString() => identifier;
+}
+
+/// Represents a logical property, which may have a getter, a setter, or both.
+final class Property extends _Node<internal.Field>
+    with _Visitable, _Renamable, _Excludable, _HasModifiers {
+  @meta.internal
+  Property(super._internalNode);
+
+  late final Class enclosingClass;
+
+  @override
+  void accept(Visitor visitor) {
+    visitor.visitProperty(this);
+  }
+
+  @override
+  bool isNameAllowed(String name) {
+    if (enclosingClass.kind == DeclKind.interfaceKind &&
+        _disallowedInInterface.contains(name)) {
+      return false;
+    }
+    return _validDartIdentifier.hasMatch(name) && !_keywords.contains(name);
+  }
+
+  @override
+  String get identifier => originalName;
+
+  @override
+  String toString() => identifier;
+}
+
+/// Represents a Dart method.
+final class Method extends _Node<internal.Method>
+    with
+        _Visitable,
+        _HasVisitableChildren,
+        _Renamable,
+        _Excludable,
+        _HasModifiers {
+  @meta.internal
+  Method(super._internalNode, this.parameters) {
+    for (final param in parameters) {
+      param.enclosingMethod = this;
+    }
+  }
+
+  late final Class enclosingClass;
+  final UnmodifiableListView<MethodParameter> parameters;
+
+  @override
+  void accept(Visitor visitor) {
+    visitor.visitMethod(this);
+  }
+
+  @override
+  void visitChildren(Visitor visitor) {
+    for (final parameter in parameters) {
+      parameter.accept(visitor);
+    }
+  }
+
+  @override
+  bool isNameAllowed(String name) {
+    if (enclosingClass.kind == DeclKind.interfaceKind &&
+        _disallowedInInterface.contains(name)) {
+      return false;
+    }
+    return _validDartIdentifier.hasMatch(name) && !_keywords.contains(name);
+  }
+
+  @override
+  String get identifier => _internalNode.javaSig;
+
+  @override
+  String toString() => identifier;
+}
+
+/// Represents a parameter of a [Method].
+final class MethodParameter extends _Node<internal.Param>
+    with _Visitable, _Renamable {
+  @meta.internal
+  MethodParameter(super._internalNode);
+
+  late final Method enclosingMethod;
+
+  @override
+  void accept(Visitor visitor) {
+    visitor.visitMethodParameter(this);
+  }
+
+  @override
+  bool isNameAllowed(String name) {
+    return _validDartIdentifier.hasMatch(name) && !_keywords.contains(name);
+  }
+
+  @override
+  String get identifier =>
+      _internalNode.method.params.indexOf(_internalNode).toString();
+}
diff --git a/pkgs/jnigen/lib/src/transformers/validator.dart b/pkgs/jnigen/lib/src/transformers/validator.dart
new file mode 100644
index 0000000..9e9ad9a
--- /dev/null
+++ b/pkgs/jnigen/lib/src/transformers/validator.dart
@@ -0,0 +1,158 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'graph.dart';
+
+final class ValidationError extends Error {
+  final String message;
+
+  ValidationError(this.message);
+
+  @override
+  String toString() => 'Validation error: $message';
+}
+
+final class Validator extends Visitor {
+  String _usedNameClusters(Map<String, List<String>> usedNames) {
+    final usedNameClusters = StringBuffer();
+    for (final MapEntry(key: name, value: identifiers) in usedNames.entries) {
+      if (identifiers.length > 1) {
+        usedNameClusters.write('\n\n"$name": \n- ');
+        usedNameClusters.writeAll(identifiers, '\n- ');
+      }
+    }
+    return usedNameClusters.toString();
+  }
+
+  @override
+  void visit(Bindings bindings) {
+    for (final file in bindings.files) {
+      final usedNames = <String, List<String>>{};
+      for (final cls in file.classes) {
+        if (cls.name == null) {
+          throw ValidationError('No name has been provided for $cls.');
+        }
+        (usedNames[cls.name!] ??= []).add(cls.identifier);
+      }
+      final usedNameClusters = _usedNameClusters(usedNames);
+      final hasValidNaming = usedNameClusters.isEmpty;
+      if (!hasValidNaming) {
+        throw ValidationError('''
+The following members are named the same in file "${file.path}":$usedNameClusters
+
+To fix the problem, choose different names for the classes.
+''');
+      }
+    }
+  }
+
+  @override
+  void visitClass(Class cls) {
+    if (!cls.isNameAllowed(cls.name!)) {
+      throw ValidationError(
+          'The class "$cls" cannot have the name "${cls.name}".');
+    }
+    if (cls.isTopLevel && cls.kind != DeclKind.packageKind) {
+      // Validate whether this class can be top-level.
+      final includedNonStaticProperties = cls.properties
+          .where((property) => !property.isExcluded && !property.isStatic);
+      final includedNonStaticMethods =
+          cls.methods.where((method) => !method.isExcluded && !method.isStatic);
+      if (includedNonStaticProperties.isNotEmpty ||
+          includedNonStaticMethods.isNotEmpty) {
+        final instanceMembers = [
+          ...includedNonStaticMethods,
+          ...includedNonStaticProperties
+        ].map((member) => '- $member').join('\n');
+        throw ValidationError('''
+Class "$cls" cannot be converted to a top-level container as it has non-excluded
+instance members:
+
+$instanceMembers
+
+To fix this problem, either set isTopLevel to false, or exclude all of the
+instance members of this class.
+''');
+      }
+    }
+    // Validate the namings of included members.
+    final usedNames = <String, List<String>>{};
+    for (final property in cls.properties) {
+      if (property.name == null) {
+        throw ValidationError(
+            'No name has been provided for property $property of class '
+            '${property.enclosingClass}.');
+      }
+      (usedNames[property.name!] ??= []).add(property.identifier);
+    }
+    for (final method in cls.methods) {
+      if (method.name == null) {
+        throw ValidationError(
+            'No name has been provided for method $method of class '
+            '${method.enclosingClass}.');
+      }
+      (usedNames[method.name!] ??= []).add(method.identifier);
+    }
+    final usedNameClusters = _usedNameClusters(usedNames);
+    final hasValidNaming = usedNameClusters.isEmpty;
+    if (!hasValidNaming) {
+      throw ValidationError('''
+The following members are named the same in class "$cls":$usedNameClusters
+
+To fix the problem, choose different names for the members.
+''');
+    }
+    super.visitClass(cls);
+  }
+
+  @override
+  void visitProperty(Property property) {
+    if (!property.isNameAllowed(property.name!)) {
+      throw ValidationError('''
+The property "$property" of class "${property.enclosingClass}" cannot have the
+name "${property.name}".
+''');
+    }
+  }
+
+  @override
+  void visitMethod(Method method) {
+    if (!method.isNameAllowed(method.name!)) {
+      throw ValidationError('''
+The method "$method" of class "${method.enclosingClass}" cannot have the
+name "${method.name}".
+''');
+    }
+    final usedNames = <String>{};
+    for (final parameter in method.parameters) {
+      if (parameter.name == null) {
+        throw ValidationError(
+            'No name has been provided for parameter $parameter of method '
+            '${parameter.enclosingMethod} of class '
+            '${parameter.enclosingMethod.enclosingClass}.');
+      }
+      if (usedNames.contains(parameter.name)) {
+        throw ValidationError('''
+The parameter names of method "$method" of class "${method.enclosingClass}"
+clash with one another.
+
+To fix the problem, choose different names for the parameters.
+''');
+      }
+    }
+    super.visitMethod(method);
+  }
+
+  @override
+  void visitMethodParameter(MethodParameter methodParameter) {
+    if (!methodParameter.isNameAllowed(methodParameter.name!)) {
+      final method = methodParameter.enclosingMethod;
+      final enclosingClass = method.enclosingClass;
+      throw ValidationError('''
+The parameter at index $methodParameter of method "$method" of class
+"$enclosingClass" cannot have the name "${methodParameter.name}".
+''');
+    }
+  }
+}
diff --git a/pkgs/jnigen/test/package_resolver_test.dart b/pkgs/jnigen/test/package_resolver_test.dart
deleted file mode 100644
index 5959552..0000000
--- a/pkgs/jnigen/test/package_resolver_test.dart
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:jnigen/src/bindings/resolver.dart';
-import 'package:jnigen/src/elements/elements.dart';
-import 'package:test/test.dart';
-
-import 'test_util/test_util.dart';
-
-class ResolverTest {
-  ResolverTest(this.binaryName, this.expectedImport, this.expectedName);
-  String binaryName;
-  String expectedImport;
-  String expectedName;
-}
-
-void main() async {
-  await checkLocallyBuiltDependencies();
-  final resolver = Resolver(
-    importedClasses: {
-      'org.apache.pdfbox.pdmodel.PDDocument': ClassDecl(
-        declKind: DeclKind.classKind,
-        binaryName: 'org.apache.pdfbox.pdmodel.PDDocument',
-      )..path = 'package:pdfbox/pdfbox.dart',
-      'android.os.Process': ClassDecl(
-        declKind: DeclKind.classKind,
-        binaryName: 'android.os.Process',
-      )..path = 'package:android/os.dart',
-    },
-    currentClass: 'a.b.N',
-    inputClassNames: {
-      'a.b.C',
-      'a.b.c.D',
-      'a.b.c.d.E',
-      'a.X',
-      'e.f.G',
-      'e.F',
-      'a.g.Y',
-      'a.m.n.P'
-    },
-  );
-
-  final tests = [
-    // Absolute imports resolved using import map
-    ResolverTest(
-        'android.os.Process', 'package:android/os.dart', r'process$_.'),
-    ResolverTest('org.apache.pdfbox.pdmodel.PDDocument',
-        'package:pdfbox/pdfbox.dart', r'pddocument$_.'),
-    // Relative imports
-    // inner package
-    ResolverTest('a.b.c.D', 'c/D.dart', r'd$_.'),
-    // inner package, deeper
-    ResolverTest('a.b.c.d.E', 'c/d/E.dart', r'e$_.'),
-    // parent package
-    ResolverTest('a.X', '../X.dart', r'x$_.'),
-    // unrelated package in same translation unit
-    ResolverTest('e.f.G', '../../e/f/G.dart', r'g$_.'),
-    ResolverTest('e.F', '../../e/F.dart', r'f$_.'),
-    // neighbour package
-    ResolverTest('a.g.Y', '../g/Y.dart', r'y$_.'),
-    // inner package of a neighbour package
-    ResolverTest('a.m.n.P', '../m/n/P.dart', r'p$_.'),
-  ];
-
-  for (var testCase in tests) {
-    final binaryName = testCase.binaryName;
-    final packageName = Resolver.getFileClassName(binaryName);
-    test(
-        'getImport $binaryName',
-        () => expect(resolver.getImport(packageName, binaryName),
-            equals(testCase.expectedImport)));
-    test(
-        'resolve $binaryName',
-        () => expect(
-            resolver.resolvePrefix(ClassDecl(
-              declKind: DeclKind.classKind,
-              binaryName: binaryName,
-            )..path = ''),
-            equals(testCase.expectedName)));
-  }
-}
diff --git a/pkgs/jnigen/test/renamer_test.dart b/pkgs/jnigen/test/renamer_test.dart
index 1da7f18..a026530 100644
--- a/pkgs/jnigen/test/renamer_test.dart
+++ b/pkgs/jnigen/test/renamer_test.dart
@@ -4,11 +4,11 @@
 
 import 'package:jnigen/jnigen.dart';
 import 'package:jnigen/src/bindings/linker.dart';
-import 'package:jnigen/src/bindings/renamer.dart';
+// import 'package:jnigen/src/bindings/renamer.dart';
 import 'package:test/test.dart';
 
-extension on Iterable<ClassMember> {
-  List<String> get finalNames => map((c) => c.finalName).toList();
+extension on Iterable<Renamable> {
+  List<String> get finalNames => map((c) => c.finalName!).toList();
 }
 
 Future<void> rename(Classes classes) async {
@@ -22,7 +22,7 @@
     classes: [],
   );
   await classes.accept(Linker(config));
-  classes.accept(Renamer(config));
+  // classes.accept(Renamer(config));
 }
 
 void main() {
diff --git a/pkgs/jnigen/test/simple_package_test/bindings/simple_package.dart b/pkgs/jnigen/test/simple_package_test/bindings/simple_package.dart
index 7969db3..78900ed 100644
--- a/pkgs/jnigen/test/simple_package_test/bindings/simple_package.dart
+++ b/pkgs/jnigen/test/simple_package_test/bindings/simple_package.dart
@@ -38,6 +38,7 @@
 import 'dart:core' as core$_;
 
 import 'package:jni/_internal.dart' as jni$_;
+
 import 'package:jni/jni.dart' as jni$_;
 
 /// from: `com.github.dart_lang.jnigen.simple_package.Example$Nested$NestedTwice`
@@ -97,6 +98,29 @@
         _new$(_class.reference.pointer, _id_new$ as jni$_.JMethodIDPtr)
             .reference);
   }
+
+  static final _id_$_clinit_ = _class.staticMethodId(
+    r'<clinit>',
+    r'()V',
+  );
+
+  static final _$_clinit_ = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JThrowablePtr Function(
+                jni$_.Pointer<jni$_.Void>,
+                jni$_.JMethodIDPtr,
+              )>>('globalEnv_CallStaticVoidMethod')
+      .asFunction<
+          jni$_.JThrowablePtr Function(
+            jni$_.Pointer<jni$_.Void>,
+            jni$_.JMethodIDPtr,
+          )>();
+
+  /// from: `static void <clinit>()`
+  static void $_clinit_() {
+    _$_clinit_(_class.reference.pointer, _id_$_clinit_ as jni$_.JMethodIDPtr)
+        .check();
+  }
 }
 
 final class $Example$Nested$NestedTwice$NullableType$
@@ -199,6 +223,18 @@
 
   /// The type which includes information such as the signature of this class.
   static const jni$_.JType<Example$Nested> type = $Example$Nested$Type$();
+  static final _id_value = _class.instanceFieldId(
+    r'value',
+    r'Z',
+  );
+
+  /// from: `private boolean value`
+  bool get value => _id_value.get(this, const jni$_.jbooleanType());
+
+  /// from: `private boolean value`
+  set value(bool value) =>
+      _id_value.set(this, const jni$_.jbooleanType(), value);
+
   static final _id_new$ = _class.constructorId(
     r'(Z)V',
   );
@@ -421,11 +457,11 @@
   /// from: `public void <init>(com.github.dart_lang.jnigen.simple_package.Example $outerClass)`
   /// The returned object must be released after use, by calling the [release] method.
   factory Example$NonStaticNested(
-    Example $outerClass,
+    Example $$outerClass,
   ) {
-    final _$$outerClass = $outerClass.reference;
+    final _$$$outerClass = $$outerClass.reference;
     return Example$NonStaticNested.fromReference(_new$(_class.reference.pointer,
-            _id_new$ as jni$_.JMethodIDPtr, _$$outerClass.pointer)
+            _id_new$ as jni$_.JMethodIDPtr, _$$$outerClass.pointer)
         .reference);
   }
 }
@@ -561,6 +597,139 @@
   static jni$_.JObject? get unusedRandom =>
       _id_unusedRandom.get(_class, const jni$_.$JObject$NullableType$());
 
+  static final _id_amount = _class.staticFieldId(
+    r'amount',
+    r'I',
+  );
+
+  /// from: `private static int amount`
+  static int get amount => _id_amount.get(_class, const jni$_.jintType());
+
+  /// from: `private static int amount`
+  static set amount(int value) =>
+      _id_amount.set(_class, const jni$_.jintType(), value);
+
+  static final _id_pi = _class.staticFieldId(
+    r'pi',
+    r'D',
+  );
+
+  /// from: `private static double pi`
+  static double get pi => _id_pi.get(_class, const jni$_.jdoubleType());
+
+  /// from: `private static double pi`
+  static set pi(double value) =>
+      _id_pi.set(_class, const jni$_.jdoubleType(), value);
+
+  static final _id_asterisk = _class.staticFieldId(
+    r'asterisk',
+    r'C',
+  );
+
+  /// from: `private static char asterisk`
+  static int get asterisk => _id_asterisk.get(_class, const jni$_.jcharType());
+
+  /// from: `private static char asterisk`
+  static set asterisk(int value) =>
+      _id_asterisk.set(_class, const jni$_.jcharType(), value);
+
+  static final _id_name = _class.staticFieldId(
+    r'name',
+    r'Ljava/lang/String;',
+  );
+
+  /// from: `private static java.lang.String name`
+  /// The returned object must be released after use, by calling the [release] method.
+  static jni$_.JString? get name =>
+      _id_name.get(_class, const jni$_.$JString$NullableType$());
+
+  /// from: `private static java.lang.String name`
+  /// The returned object must be released after use, by calling the [release] method.
+  static set name(jni$_.JString? value) =>
+      _id_name.set(_class, const jni$_.$JString$NullableType$(), value);
+
+  static final _id_nested = _class.staticFieldId(
+    r'nested',
+    r'Lcom/github/dart_lang/jnigen/simple_package/Example$Nested;',
+  );
+
+  /// from: `private static com.github.dart_lang.jnigen.simple_package.Example$Nested nested`
+  /// The returned object must be released after use, by calling the [release] method.
+  static Example$Nested? get nested =>
+      _id_nested.get(_class, const $Example$Nested$NullableType$());
+
+  /// from: `private static com.github.dart_lang.jnigen.simple_package.Example$Nested nested`
+  /// The returned object must be released after use, by calling the [release] method.
+  static set nested(Example$Nested? value) =>
+      _id_nested.set(_class, const $Example$Nested$NullableType$(), value);
+
+  static final _id_number = _class.instanceFieldId(
+    r'number',
+    r'I',
+  );
+
+  /// from: `private int number`
+  int get number => _id_number.get(this, const jni$_.jintType());
+
+  /// from: `private int number`
+  set number(int value) => _id_number.set(this, const jni$_.jintType(), value);
+
+  static final _id_isUp = _class.instanceFieldId(
+    r'isUp',
+    r'Z',
+  );
+
+  /// from: `private boolean isUp`
+  bool get isUp => _id_isUp.get(this, const jni$_.jbooleanType());
+
+  /// from: `private boolean isUp`
+  set isUp(bool value) => _id_isUp.set(this, const jni$_.jbooleanType(), value);
+
+  static final _id_codename = _class.instanceFieldId(
+    r'codename',
+    r'Ljava/lang/String;',
+  );
+
+  /// from: `private java.lang.String codename`
+  /// The returned object must be released after use, by calling the [release] method.
+  jni$_.JString? get codename =>
+      _id_codename.get(this, const jni$_.$JString$NullableType$());
+
+  /// from: `private java.lang.String codename`
+  /// The returned object must be released after use, by calling the [release] method.
+  set codename(jni$_.JString? value) =>
+      _id_codename.set(this, const jni$_.$JString$NullableType$(), value);
+
+  static final _id_random = _class.instanceFieldId(
+    r'random',
+    r'Ljava/util/Random;',
+  );
+
+  /// from: `private java.util.Random random`
+  /// The returned object must be released after use, by calling the [release] method.
+  jni$_.JObject? get random =>
+      _id_random.get(this, const jni$_.$JObject$NullableType$());
+
+  /// from: `private java.util.Random random`
+  /// The returned object must be released after use, by calling the [release] method.
+  set random(jni$_.JObject? value) =>
+      _id_random.set(this, const jni$_.$JObject$NullableType$(), value);
+
+  static final _id_protectedField = _class.instanceFieldId(
+    r'protectedField',
+    r'Ljava/util/Random;',
+  );
+
+  /// from: `protected java.util.Random protectedField`
+  /// The returned object must be released after use, by calling the [release] method.
+  jni$_.JObject? get protectedField =>
+      _id_protectedField.get(this, const jni$_.$JObject$NullableType$());
+
+  /// from: `protected java.util.Random protectedField`
+  /// The returned object must be released after use, by calling the [release] method.
+  set protectedField(jni$_.JObject? value) =>
+      _id_protectedField.set(this, const jni$_.$JObject$NullableType$(), value);
+
   static final _id_getAmount = _class.staticMethodId(
     r'getAmount',
     r'()I',
@@ -1147,6 +1316,77 @@
         .object<jni$_.JString?>(const jni$_.$JString$NullableType$());
   }
 
+  static final _id_privateMethod = _class.instanceMethodId(
+    r'privateMethod',
+    r'(Ljava/lang/String;Ljava/lang/String;)V',
+  );
+
+  static final _privateMethod = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JThrowablePtr Function(
+                  jni$_.Pointer<jni$_.Void>,
+                  jni$_.JMethodIDPtr,
+                  jni$_.VarArgs<
+                      (
+                        jni$_.Pointer<jni$_.Void>,
+                        jni$_.Pointer<jni$_.Void>
+                      )>)>>('globalEnv_CallVoidMethod')
+      .asFunction<
+          jni$_.JThrowablePtr Function(
+              jni$_.Pointer<jni$_.Void>,
+              jni$_.JMethodIDPtr,
+              jni$_.Pointer<jni$_.Void>,
+              jni$_.Pointer<jni$_.Void>)>();
+
+  /// from: `private void privateMethod(java.lang.String string, java.lang.String string1)`
+  void privateMethod(
+    jni$_.JString? string,
+    jni$_.JString? string1,
+  ) {
+    final _$string = string?.reference ?? jni$_.jNullReference;
+    final _$string1 = string1?.reference ?? jni$_.jNullReference;
+    _privateMethod(reference.pointer, _id_privateMethod as jni$_.JMethodIDPtr,
+            _$string.pointer, _$string1.pointer)
+        .check();
+  }
+
+  static final _id_protectedMethod = _class.instanceMethodId(
+    r'protectedMethod',
+    r'(Ljava/lang/String;Ljava/lang/String;)V',
+  );
+
+  static final _protectedMethod = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JThrowablePtr Function(
+                  jni$_.Pointer<jni$_.Void>,
+                  jni$_.JMethodIDPtr,
+                  jni$_.VarArgs<
+                      (
+                        jni$_.Pointer<jni$_.Void>,
+                        jni$_.Pointer<jni$_.Void>
+                      )>)>>('globalEnv_CallVoidMethod')
+      .asFunction<
+          jni$_.JThrowablePtr Function(
+              jni$_.Pointer<jni$_.Void>,
+              jni$_.JMethodIDPtr,
+              jni$_.Pointer<jni$_.Void>,
+              jni$_.Pointer<jni$_.Void>)>();
+
+  /// from: `protected void protectedMethod(java.lang.String string, java.lang.String string1)`
+  void protectedMethod(
+    jni$_.JString? string,
+    jni$_.JString? string1,
+  ) {
+    final _$string = string?.reference ?? jni$_.jNullReference;
+    final _$string1 = string1?.reference ?? jni$_.jNullReference;
+    _protectedMethod(
+            reference.pointer,
+            _id_protectedMethod as jni$_.JMethodIDPtr,
+            _$string.pointer,
+            _$string1.pointer)
+        .check();
+  }
+
   static final _id_finalMethod = _class.instanceMethodId(
     r'finalMethod',
     r'()V',
@@ -1719,6 +1959,29 @@
             _$list.pointer)
         .check();
   }
+
+  static final _id_$_clinit_ = _class.staticMethodId(
+    r'<clinit>',
+    r'()V',
+  );
+
+  static final _$_clinit_ = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JThrowablePtr Function(
+                jni$_.Pointer<jni$_.Void>,
+                jni$_.JMethodIDPtr,
+              )>>('globalEnv_CallStaticVoidMethod')
+      .asFunction<
+          jni$_.JThrowablePtr Function(
+            jni$_.Pointer<jni$_.Void>,
+            jni$_.JMethodIDPtr,
+          )>();
+
+  /// from: `static void <clinit>()`
+  static void $_clinit_() {
+    _$_clinit_(_class.reference.pointer, _id_$_clinit_ as jni$_.JMethodIDPtr)
+        .check();
+  }
 }
 
 final class $Example$NullableType$ extends jni$_.JType<Example?> {
@@ -2396,6 +2659,29 @@
         _new$(_class.reference.pointer, _id_new$ as jni$_.JMethodIDPtr)
             .reference);
   }
+
+  static final _id_$_clinit_ = _class.staticMethodId(
+    r'<clinit>',
+    r'()V',
+  );
+
+  static final _$_clinit_ = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JThrowablePtr Function(
+                jni$_.Pointer<jni$_.Void>,
+                jni$_.JMethodIDPtr,
+              )>>('globalEnv_CallStaticVoidMethod')
+      .asFunction<
+          jni$_.JThrowablePtr Function(
+            jni$_.Pointer<jni$_.Void>,
+            jni$_.JMethodIDPtr,
+          )>();
+
+  /// from: `static void <clinit>()`
+  static void $_clinit_() {
+    _$_clinit_(_class.reference.pointer, _id_$_clinit_ as jni$_.JMethodIDPtr)
+        .check();
+  }
 }
 
 final class $Fields$Nested$NullableType$ extends jni$_.JType<Fields$Nested?> {
@@ -2651,6 +2937,29 @@
         _new$(_class.reference.pointer, _id_new$ as jni$_.JMethodIDPtr)
             .reference);
   }
+
+  static final _id_$_clinit_ = _class.staticMethodId(
+    r'<clinit>',
+    r'()V',
+  );
+
+  static final _$_clinit_ = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JThrowablePtr Function(
+                jni$_.Pointer<jni$_.Void>,
+                jni$_.JMethodIDPtr,
+              )>>('globalEnv_CallStaticVoidMethod')
+      .asFunction<
+          jni$_.JThrowablePtr Function(
+            jni$_.Pointer<jni$_.Void>,
+            jni$_.JMethodIDPtr,
+          )>();
+
+  /// from: `static void <clinit>()`
+  static void $_clinit_() {
+    _$_clinit_(_class.reference.pointer, _id_$_clinit_ as jni$_.JMethodIDPtr)
+        .check();
+  }
 }
 
 final class $Fields$NullableType$ extends jni$_.JType<Fields?> {
@@ -2781,6 +3090,29 @@
         _new$(_class.reference.pointer, _id_new$ as jni$_.JMethodIDPtr)
             .reference);
   }
+
+  static final _id_$_clinit_ = _class.staticMethodId(
+    r'<clinit>',
+    r'()V',
+  );
+
+  static final _$_clinit_ = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JThrowablePtr Function(
+                jni$_.Pointer<jni$_.Void>,
+                jni$_.JMethodIDPtr,
+              )>>('globalEnv_CallStaticVoidMethod')
+      .asFunction<
+          jni$_.JThrowablePtr Function(
+            jni$_.Pointer<jni$_.Void>,
+            jni$_.JMethodIDPtr,
+          )>();
+
+  /// from: `static void <clinit>()`
+  static void $_clinit_() {
+    _$_clinit_(_class.reference.pointer, _id_$_clinit_ as jni$_.JMethodIDPtr)
+        .check();
+  }
 }
 
 final class $C2$NullableType$ extends jni$_.JType<C2?> {
@@ -3103,12 +3435,12 @@
         .boolean;
   }
 
-  static final _id_hashCode$1 = _class.instanceMethodId(
+  static final _id_hashCode = _class.instanceMethodId(
     r'hashCode',
     r'()I',
   );
 
-  static final _hashCode$1 = jni$_.ProtectedJniExtensions.lookup<
+  static final _hashCode = jni$_.ProtectedJniExtensions.lookup<
           jni$_.NativeFunction<
               jni$_.JniResult Function(
                 jni$_.Pointer<jni$_.Void>,
@@ -3121,8 +3453,8 @@
           )>();
 
   /// from: `public int hashCode()`
-  int hashCode$1() {
-    return _hashCode$1(reference.pointer, _id_hashCode$1 as jni$_.JMethodIDPtr)
+  int hashCode() {
+    return _hashCode(reference.pointer, _id_hashCode as jni$_.JMethodIDPtr)
         .integer;
   }
 }
@@ -3309,6 +3641,38 @@
         .object<Colors?>(const $Colors$NullableType$());
   }
 
+  static final _id_new$ = _class.constructorId(
+    r'(Ljava/lang/String;II)V',
+  );
+
+  static final _new$ = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JniResult Function(
+                  jni$_.Pointer<jni$_.Void>,
+                  jni$_.JMethodIDPtr,
+                  jni$_.VarArgs<
+                      (
+                        jni$_.Pointer<jni$_.Void>,
+                        jni$_.Int32,
+                        jni$_.Int32
+                      )>)>>('globalEnv_NewObject')
+      .asFunction<
+          jni$_.JniResult Function(jni$_.Pointer<jni$_.Void>,
+              jni$_.JMethodIDPtr, jni$_.Pointer<jni$_.Void>, int, int)>();
+
+  /// from: `private void <init>(java.lang.String string, int i, int i1)`
+  /// The returned object must be released after use, by calling the [release] method.
+  factory Colors(
+    jni$_.JString? string,
+    int i,
+    int i1,
+  ) {
+    final _$string = string?.reference ?? jni$_.jNullReference;
+    return Colors.fromReference(_new$(_class.reference.pointer,
+            _id_new$ as jni$_.JMethodIDPtr, _$string.pointer, i, i1)
+        .reference);
+  }
+
   static final _id_toRGB = _class.instanceMethodId(
     r'toRGB',
     r'()Lcom/github/dart_lang/jnigen/enums/Colors$RGB;',
@@ -3332,6 +3696,29 @@
     return _toRGB(reference.pointer, _id_toRGB as jni$_.JMethodIDPtr)
         .object<Colors$RGB?>(const $Colors$RGB$NullableType$());
   }
+
+  static final _id_$_clinit_ = _class.staticMethodId(
+    r'<clinit>',
+    r'()V',
+  );
+
+  static final _$_clinit_ = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JThrowablePtr Function(
+                jni$_.Pointer<jni$_.Void>,
+                jni$_.JMethodIDPtr,
+              )>>('globalEnv_CallStaticVoidMethod')
+      .asFunction<
+          jni$_.JThrowablePtr Function(
+            jni$_.Pointer<jni$_.Void>,
+            jni$_.JMethodIDPtr,
+          )>();
+
+  /// from: `static void <clinit>()`
+  static void $_clinit_() {
+    _$_clinit_(_class.reference.pointer, _id_$_clinit_ as jni$_.JMethodIDPtr)
+        .check();
+  }
 }
 
 final class $Colors$NullableType$ extends jni$_.JType<Colors?> {
@@ -3715,30 +4102,30 @@
   /// from: `public void <init>(com.github.dart_lang.jnigen.generics.GrandParent$Parent<T, S> $outerClass, U object)`
   /// The returned object must be released after use, by calling the [release] method.
   factory GrandParent$Parent$Child(
-    GrandParent$Parent<$T?, $S?> $outerClass,
+    GrandParent$Parent<$T?, $S?> $$outerClass,
     $U? object, {
     jni$_.JType<$T>? T,
     jni$_.JType<$S>? S,
     required jni$_.JType<$U> U,
   }) {
     T ??= jni$_.lowestCommonSuperType([
-      ($outerClass.$type
+      ($$outerClass.$type
               as $GrandParent$Parent$Type$<core$_.dynamic, core$_.dynamic>)
           .T,
     ]) as jni$_.JType<$T>;
     S ??= jni$_.lowestCommonSuperType([
-      ($outerClass.$type
+      ($$outerClass.$type
               as $GrandParent$Parent$Type$<core$_.dynamic, core$_.dynamic>)
           .S,
     ]) as jni$_.JType<$S>;
-    final _$$outerClass = $outerClass.reference;
+    final _$$$outerClass = $$outerClass.reference;
     final _$object = object?.reference ?? jni$_.jNullReference;
     return GrandParent$Parent$Child<$T, $S, $U>.fromReference(
         T,
         S,
         U,
         _new$(_class.reference.pointer, _id_new$ as jni$_.JMethodIDPtr,
-                _$$outerClass.pointer, _$object.pointer)
+                _$$$outerClass.pointer, _$object.pointer)
             .reference);
   }
 }
@@ -3965,21 +4352,21 @@
   /// from: `public void <init>(com.github.dart_lang.jnigen.generics.GrandParent<T> $outerClass, S object)`
   /// The returned object must be released after use, by calling the [release] method.
   factory GrandParent$Parent(
-    GrandParent<$T?> $outerClass,
+    GrandParent<$T?> $$outerClass,
     $S? object, {
     jni$_.JType<$T>? T,
     required jni$_.JType<$S> S,
   }) {
     T ??= jni$_.lowestCommonSuperType([
-      ($outerClass.$type as $GrandParent$Type$<core$_.dynamic>).T,
+      ($$outerClass.$type as $GrandParent$Type$<core$_.dynamic>).T,
     ]) as jni$_.JType<$T>;
-    final _$$outerClass = $outerClass.reference;
+    final _$$$outerClass = $$outerClass.reference;
     final _$object = object?.reference ?? jni$_.jNullReference;
     return GrandParent$Parent<$T, $S>.fromReference(
         T,
         S,
         _new$(_class.reference.pointer, _id_new$ as jni$_.JMethodIDPtr,
-                _$$outerClass.pointer, _$object.pointer)
+                _$$$outerClass.pointer, _$object.pointer)
             .reference);
   }
 }
@@ -4191,23 +4578,23 @@
   /// from: `public void <init>(com.github.dart_lang.jnigen.generics.GrandParent$StaticParent<S> $outerClass, S object, U object1)`
   /// The returned object must be released after use, by calling the [release] method.
   factory GrandParent$StaticParent$Child(
-    GrandParent$StaticParent<$S?> $outerClass,
+    GrandParent$StaticParent<$S?> $$outerClass,
     $S? object,
     $U? object1, {
     jni$_.JType<$S>? S,
     required jni$_.JType<$U> U,
   }) {
     S ??= jni$_.lowestCommonSuperType([
-      ($outerClass.$type as $GrandParent$StaticParent$Type$<core$_.dynamic>).S,
+      ($$outerClass.$type as $GrandParent$StaticParent$Type$<core$_.dynamic>).S,
     ]) as jni$_.JType<$S>;
-    final _$$outerClass = $outerClass.reference;
+    final _$$$outerClass = $$outerClass.reference;
     final _$object = object?.reference ?? jni$_.jNullReference;
     final _$object1 = object1?.reference ?? jni$_.jNullReference;
     return GrandParent$StaticParent$Child<$S, $U>.fromReference(
         S,
         U,
         _new$(_class.reference.pointer, _id_new$ as jni$_.JMethodIDPtr,
-                _$$outerClass.pointer, _$object.pointer, _$object1.pointer)
+                _$$$outerClass.pointer, _$object.pointer, _$object1.pointer)
             .reference);
   }
 }
@@ -4910,26 +5297,26 @@
   /// from: `public void <init>(com.github.dart_lang.jnigen.generics.MyMap<K, V> $outerClass, K object, V object1)`
   /// The returned object must be released after use, by calling the [release] method.
   factory MyMap$MyEntry(
-    MyMap<$K?, $V?> $outerClass,
+    MyMap<$K?, $V?> $$outerClass,
     $K? object,
     $V? object1, {
     jni$_.JType<$K>? K,
     jni$_.JType<$V>? V,
   }) {
     K ??= jni$_.lowestCommonSuperType([
-      ($outerClass.$type as $MyMap$Type$<core$_.dynamic, core$_.dynamic>).K,
+      ($$outerClass.$type as $MyMap$Type$<core$_.dynamic, core$_.dynamic>).K,
     ]) as jni$_.JType<$K>;
     V ??= jni$_.lowestCommonSuperType([
-      ($outerClass.$type as $MyMap$Type$<core$_.dynamic, core$_.dynamic>).V,
+      ($$outerClass.$type as $MyMap$Type$<core$_.dynamic, core$_.dynamic>).V,
     ]) as jni$_.JType<$V>;
-    final _$$outerClass = $outerClass.reference;
+    final _$$$outerClass = $$outerClass.reference;
     final _$object = object?.reference ?? jni$_.jNullReference;
     final _$object1 = object1?.reference ?? jni$_.jNullReference;
     return MyMap$MyEntry<$K, $V>.fromReference(
         K,
         V,
         _new$(_class.reference.pointer, _id_new$ as jni$_.JMethodIDPtr,
-                _$$outerClass.pointer, _$object.pointer, _$object1.pointer)
+                _$$$outerClass.pointer, _$object.pointer, _$object1.pointer)
             .reference);
   }
 }
@@ -5087,6 +5474,23 @@
     );
   }
 
+  static final _id_map = _class.instanceFieldId(
+    r'map',
+    r'Ljava/util/Map;',
+  );
+
+  /// from: `private java.util.Map<K, V> map`
+  /// The returned object must be released after use, by calling the [release] method.
+  jni$_.JMap<$K?, $V?>? get map => _id_map.get(this,
+      jni$_.$JMap$NullableType$<$K?, $V?>(K.nullableType, V.nullableType));
+
+  /// from: `private java.util.Map<K, V> map`
+  /// The returned object must be released after use, by calling the [release] method.
+  set map(jni$_.JMap<$K?, $V?>? value) => _id_map.set(
+      this,
+      jni$_.$JMap$NullableType$<$K?, $V?>(K.nullableType, V.nullableType),
+      value);
+
   static final _id_new$ = _class.constructorId(
     r'()V',
   );
@@ -5345,6 +5749,21 @@
     );
   }
 
+  static final _id_stack = _class.instanceFieldId(
+    r'stack',
+    r'Ljava/util/Stack;',
+  );
+
+  /// from: `private java.util.Stack<T> stack`
+  /// The returned object must be released after use, by calling the [release] method.
+  jni$_.JObject? get stack =>
+      _id_stack.get(this, const jni$_.$JObject$NullableType$());
+
+  /// from: `private java.util.Stack<T> stack`
+  /// The returned object must be released after use, by calling the [release] method.
+  set stack(jni$_.JObject? value) =>
+      _id_stack.set(this, const jni$_.$JObject$NullableType$(), value);
+
   static final _id_new$ = _class.constructorId(
     r'()V',
   );
@@ -5749,6 +6168,95 @@
         _new$(_class.reference.pointer, _id_new$ as jni$_.JMethodIDPtr)
             .reference);
   }
+
+  static final _id_get = _class.instanceMethodId(
+    r'get',
+    r'(Ljava/lang/String;)Ljava/lang/Object;',
+  );
+
+  static final _get = jni$_.ProtectedJniExtensions.lookup<
+              jni$_.NativeFunction<
+                  jni$_.JniResult Function(
+                      jni$_.Pointer<jni$_.Void>,
+                      jni$_.JMethodIDPtr,
+                      jni$_.VarArgs<(jni$_.Pointer<jni$_.Void>,)>)>>(
+          'globalEnv_CallObjectMethod')
+      .asFunction<
+          jni$_.JniResult Function(jni$_.Pointer<jni$_.Void>,
+              jni$_.JMethodIDPtr, jni$_.Pointer<jni$_.Void>)>();
+
+  /// from: `public V get(java.lang.String object)`
+  /// The returned object must be released after use, by calling the [release] method.
+  $V? get(
+    jni$_.JString? object,
+  ) {
+    final _$object = object?.reference ?? jni$_.jNullReference;
+    return _get(
+            reference.pointer, _id_get as jni$_.JMethodIDPtr, _$object.pointer)
+        .object<$V?>(V.nullableType);
+  }
+
+  static final _id_put = _class.instanceMethodId(
+    r'put',
+    r'(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;',
+  );
+
+  static final _put = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JniResult Function(
+                  jni$_.Pointer<jni$_.Void>,
+                  jni$_.JMethodIDPtr,
+                  jni$_.VarArgs<
+                      (
+                        jni$_.Pointer<jni$_.Void>,
+                        jni$_.Pointer<jni$_.Void>
+                      )>)>>('globalEnv_CallObjectMethod')
+      .asFunction<
+          jni$_.JniResult Function(
+              jni$_.Pointer<jni$_.Void>,
+              jni$_.JMethodIDPtr,
+              jni$_.Pointer<jni$_.Void>,
+              jni$_.Pointer<jni$_.Void>)>();
+
+  /// from: `public V put(java.lang.String object, V object1)`
+  /// The returned object must be released after use, by calling the [release] method.
+  $V? put(
+    jni$_.JString? object,
+    $V? object1,
+  ) {
+    final _$object = object?.reference ?? jni$_.jNullReference;
+    final _$object1 = object1?.reference ?? jni$_.jNullReference;
+    return _put(reference.pointer, _id_put as jni$_.JMethodIDPtr,
+            _$object.pointer, _$object1.pointer)
+        .object<$V?>(V.nullableType);
+  }
+
+  static final _id_entryStack = _class.instanceMethodId(
+    r'entryStack',
+    r'()Lcom/github/dart_lang/jnigen/generics/MyStack;',
+  );
+
+  static final _entryStack = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JniResult Function(
+                jni$_.Pointer<jni$_.Void>,
+                jni$_.JMethodIDPtr,
+              )>>('globalEnv_CallObjectMethod')
+      .asFunction<
+          jni$_.JniResult Function(
+            jni$_.Pointer<jni$_.Void>,
+            jni$_.JMethodIDPtr,
+          )>();
+
+  /// from: `public com.github.dart_lang.jnigen.generics.MyStack<com.github.dart_lang.jnigen.generics.MyMap$MyEntry<java.lang.String, V>> entryStack()`
+  /// The returned object must be released after use, by calling the [release] method.
+  MyStack<MyMap$MyEntry<jni$_.JString?, $V?>?>? entryStack() {
+    return _entryStack(reference.pointer, _id_entryStack as jni$_.JMethodIDPtr)
+        .object<MyStack<MyMap$MyEntry<jni$_.JString?, $V?>?>?>(
+            $MyStack$NullableType$<MyMap$MyEntry<jni$_.JString?, $V?>?>(
+                $MyMap$MyEntry$NullableType$<jni$_.JString?, $V?>(
+                    const jni$_.$JString$NullableType$(), V.nullableType)));
+  }
 }
 
 final class $StringKeyedMap$NullableType$<$V extends jni$_.JObject?>
@@ -5890,6 +6398,97 @@
         _new$(_class.reference.pointer, _id_new$ as jni$_.JMethodIDPtr)
             .reference);
   }
+
+  static final _id_get = _class.instanceMethodId(
+    r'get',
+    r'(Ljava/lang/String;)Ljava/lang/String;',
+  );
+
+  static final _get = jni$_.ProtectedJniExtensions.lookup<
+              jni$_.NativeFunction<
+                  jni$_.JniResult Function(
+                      jni$_.Pointer<jni$_.Void>,
+                      jni$_.JMethodIDPtr,
+                      jni$_.VarArgs<(jni$_.Pointer<jni$_.Void>,)>)>>(
+          'globalEnv_CallObjectMethod')
+      .asFunction<
+          jni$_.JniResult Function(jni$_.Pointer<jni$_.Void>,
+              jni$_.JMethodIDPtr, jni$_.Pointer<jni$_.Void>)>();
+
+  /// from: `public java.lang.String get(java.lang.String object)`
+  /// The returned object must be released after use, by calling the [release] method.
+  jni$_.JString? get(
+    jni$_.JString? object,
+  ) {
+    final _$object = object?.reference ?? jni$_.jNullReference;
+    return _get(
+            reference.pointer, _id_get as jni$_.JMethodIDPtr, _$object.pointer)
+        .object<jni$_.JString?>(const jni$_.$JString$NullableType$());
+  }
+
+  static final _id_put = _class.instanceMethodId(
+    r'put',
+    r'(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;',
+  );
+
+  static final _put = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JniResult Function(
+                  jni$_.Pointer<jni$_.Void>,
+                  jni$_.JMethodIDPtr,
+                  jni$_.VarArgs<
+                      (
+                        jni$_.Pointer<jni$_.Void>,
+                        jni$_.Pointer<jni$_.Void>
+                      )>)>>('globalEnv_CallObjectMethod')
+      .asFunction<
+          jni$_.JniResult Function(
+              jni$_.Pointer<jni$_.Void>,
+              jni$_.JMethodIDPtr,
+              jni$_.Pointer<jni$_.Void>,
+              jni$_.Pointer<jni$_.Void>)>();
+
+  /// from: `public java.lang.String put(java.lang.String object, java.lang.String object1)`
+  /// The returned object must be released after use, by calling the [release] method.
+  jni$_.JString? put(
+    jni$_.JString? object,
+    jni$_.JString? object1,
+  ) {
+    final _$object = object?.reference ?? jni$_.jNullReference;
+    final _$object1 = object1?.reference ?? jni$_.jNullReference;
+    return _put(reference.pointer, _id_put as jni$_.JMethodIDPtr,
+            _$object.pointer, _$object1.pointer)
+        .object<jni$_.JString?>(const jni$_.$JString$NullableType$());
+  }
+
+  static final _id_entryStack = _class.instanceMethodId(
+    r'entryStack',
+    r'()Lcom/github/dart_lang/jnigen/generics/MyStack;',
+  );
+
+  static final _entryStack = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JniResult Function(
+                jni$_.Pointer<jni$_.Void>,
+                jni$_.JMethodIDPtr,
+              )>>('globalEnv_CallObjectMethod')
+      .asFunction<
+          jni$_.JniResult Function(
+            jni$_.Pointer<jni$_.Void>,
+            jni$_.JMethodIDPtr,
+          )>();
+
+  /// from: `public com.github.dart_lang.jnigen.generics.MyStack<com.github.dart_lang.jnigen.generics.MyMap$MyEntry<java.lang.String, java.lang.String>> entryStack()`
+  /// The returned object must be released after use, by calling the [release] method.
+  MyStack<MyMap$MyEntry<jni$_.JString?, jni$_.JString?>?>? entryStack() {
+    return _entryStack(reference.pointer, _id_entryStack as jni$_.JMethodIDPtr)
+        .object<MyStack<MyMap$MyEntry<jni$_.JString?, jni$_.JString?>?>?>(
+            const $MyStack$NullableType$<
+                    MyMap$MyEntry<jni$_.JString?, jni$_.JString?>?>(
+                $MyMap$MyEntry$NullableType$<jni$_.JString?, jni$_.JString?>(
+                    jni$_.$JString$NullableType$(),
+                    jni$_.$JString$NullableType$())));
+  }
 }
 
 final class $StringMap$NullableType$ extends jni$_.JType<StringMap?> {
@@ -6012,6 +6611,77 @@
         _new$(_class.reference.pointer, _id_new$ as jni$_.JMethodIDPtr)
             .reference);
   }
+
+  static final _id_push = _class.instanceMethodId(
+    r'push',
+    r'(Ljava/lang/String;)V',
+  );
+
+  static final _push = jni$_.ProtectedJniExtensions.lookup<
+              jni$_.NativeFunction<
+                  jni$_.JThrowablePtr Function(
+                      jni$_.Pointer<jni$_.Void>,
+                      jni$_.JMethodIDPtr,
+                      jni$_.VarArgs<(jni$_.Pointer<jni$_.Void>,)>)>>(
+          'globalEnv_CallVoidMethod')
+      .asFunction<
+          jni$_.JThrowablePtr Function(jni$_.Pointer<jni$_.Void>,
+              jni$_.JMethodIDPtr, jni$_.Pointer<jni$_.Void>)>();
+
+  /// from: `public void push(java.lang.String object)`
+  void push(
+    jni$_.JString? object,
+  ) {
+    final _$object = object?.reference ?? jni$_.jNullReference;
+    _push(reference.pointer, _id_push as jni$_.JMethodIDPtr, _$object.pointer)
+        .check();
+  }
+
+  static final _id_pop = _class.instanceMethodId(
+    r'pop',
+    r'()Ljava/lang/String;',
+  );
+
+  static final _pop = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JniResult Function(
+                jni$_.Pointer<jni$_.Void>,
+                jni$_.JMethodIDPtr,
+              )>>('globalEnv_CallObjectMethod')
+      .asFunction<
+          jni$_.JniResult Function(
+            jni$_.Pointer<jni$_.Void>,
+            jni$_.JMethodIDPtr,
+          )>();
+
+  /// from: `public java.lang.String pop()`
+  /// The returned object must be released after use, by calling the [release] method.
+  jni$_.JString? pop() {
+    return _pop(reference.pointer, _id_pop as jni$_.JMethodIDPtr)
+        .object<jni$_.JString?>(const jni$_.$JString$NullableType$());
+  }
+
+  static final _id_size = _class.instanceMethodId(
+    r'size',
+    r'()I',
+  );
+
+  static final _size = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JniResult Function(
+                jni$_.Pointer<jni$_.Void>,
+                jni$_.JMethodIDPtr,
+              )>>('globalEnv_CallIntMethod')
+      .asFunction<
+          jni$_.JniResult Function(
+            jni$_.Pointer<jni$_.Void>,
+            jni$_.JMethodIDPtr,
+          )>();
+
+  /// from: `public int size()`
+  int size() {
+    return _size(reference.pointer, _id_size as jni$_.JMethodIDPtr).integer;
+  }
 }
 
 final class $StringStack$NullableType$ extends jni$_.JType<StringStack?> {
@@ -6156,6 +6826,95 @@
         _new$(_class.reference.pointer, _id_new$ as jni$_.JMethodIDPtr)
             .reference);
   }
+
+  static final _id_get = _class.instanceMethodId(
+    r'get',
+    r'(Ljava/lang/Object;)Ljava/lang/String;',
+  );
+
+  static final _get = jni$_.ProtectedJniExtensions.lookup<
+              jni$_.NativeFunction<
+                  jni$_.JniResult Function(
+                      jni$_.Pointer<jni$_.Void>,
+                      jni$_.JMethodIDPtr,
+                      jni$_.VarArgs<(jni$_.Pointer<jni$_.Void>,)>)>>(
+          'globalEnv_CallObjectMethod')
+      .asFunction<
+          jni$_.JniResult Function(jni$_.Pointer<jni$_.Void>,
+              jni$_.JMethodIDPtr, jni$_.Pointer<jni$_.Void>)>();
+
+  /// from: `public java.lang.String get(K object)`
+  /// The returned object must be released after use, by calling the [release] method.
+  jni$_.JString? get(
+    $K? object,
+  ) {
+    final _$object = object?.reference ?? jni$_.jNullReference;
+    return _get(
+            reference.pointer, _id_get as jni$_.JMethodIDPtr, _$object.pointer)
+        .object<jni$_.JString?>(const jni$_.$JString$NullableType$());
+  }
+
+  static final _id_put = _class.instanceMethodId(
+    r'put',
+    r'(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String;',
+  );
+
+  static final _put = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JniResult Function(
+                  jni$_.Pointer<jni$_.Void>,
+                  jni$_.JMethodIDPtr,
+                  jni$_.VarArgs<
+                      (
+                        jni$_.Pointer<jni$_.Void>,
+                        jni$_.Pointer<jni$_.Void>
+                      )>)>>('globalEnv_CallObjectMethod')
+      .asFunction<
+          jni$_.JniResult Function(
+              jni$_.Pointer<jni$_.Void>,
+              jni$_.JMethodIDPtr,
+              jni$_.Pointer<jni$_.Void>,
+              jni$_.Pointer<jni$_.Void>)>();
+
+  /// from: `public java.lang.String put(K object, java.lang.String object1)`
+  /// The returned object must be released after use, by calling the [release] method.
+  jni$_.JString? put(
+    $K? object,
+    jni$_.JString? object1,
+  ) {
+    final _$object = object?.reference ?? jni$_.jNullReference;
+    final _$object1 = object1?.reference ?? jni$_.jNullReference;
+    return _put(reference.pointer, _id_put as jni$_.JMethodIDPtr,
+            _$object.pointer, _$object1.pointer)
+        .object<jni$_.JString?>(const jni$_.$JString$NullableType$());
+  }
+
+  static final _id_entryStack = _class.instanceMethodId(
+    r'entryStack',
+    r'()Lcom/github/dart_lang/jnigen/generics/MyStack;',
+  );
+
+  static final _entryStack = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JniResult Function(
+                jni$_.Pointer<jni$_.Void>,
+                jni$_.JMethodIDPtr,
+              )>>('globalEnv_CallObjectMethod')
+      .asFunction<
+          jni$_.JniResult Function(
+            jni$_.Pointer<jni$_.Void>,
+            jni$_.JMethodIDPtr,
+          )>();
+
+  /// from: `public com.github.dart_lang.jnigen.generics.MyStack<com.github.dart_lang.jnigen.generics.MyMap$MyEntry<K, java.lang.String>> entryStack()`
+  /// The returned object must be released after use, by calling the [release] method.
+  MyStack<MyMap$MyEntry<$K?, jni$_.JString?>?>? entryStack() {
+    return _entryStack(reference.pointer, _id_entryStack as jni$_.JMethodIDPtr)
+        .object<MyStack<MyMap$MyEntry<$K?, jni$_.JString?>?>?>(
+            $MyStack$NullableType$<MyMap$MyEntry<$K?, jni$_.JString?>?>(
+                $MyMap$MyEntry$NullableType$<$K?, jni$_.JString?>(
+                    K.nullableType, const jni$_.$JString$NullableType$())));
+  }
 }
 
 final class $StringValuedMap$NullableType$<$K extends jni$_.JObject?>
@@ -7031,7 +7790,7 @@
                 .toPointer() ??
             jni$_.nullptr;
       }
-      if ($d == r'varCallback(Ljava/lang/String;)Ljava/lang/String;') {
+      if ($d == r'varCallback(Ljava/lang/Object;)Ljava/lang/Object;') {
         final $r = _$impls[$p]!.varCallback(
           $a![0]?.as(const jni$_.$JString$Type$(), releaseOriginal: true),
         );
@@ -8363,6 +9122,16 @@
 
   /// The type which includes information such as the signature of this class.
   static const jni$_.JType<MyRunnableRunner> type = $MyRunnableRunner$Type$();
+  static final _id_runnable = _class.instanceFieldId(
+    r'runnable',
+    r'Lcom/github/dart_lang/jnigen/interfaces/MyRunnable;',
+  );
+
+  /// from: `final com.github.dart_lang.jnigen.interfaces.MyRunnable runnable`
+  /// The returned object must be released after use, by calling the [release] method.
+  MyRunnable? get runnable =>
+      _id_runnable.get(this, const $MyRunnable$NullableType$());
+
   static final _id_error = _class.instanceFieldId(
     r'error',
     r'Ljava/lang/Throwable;',
@@ -9798,6 +10567,30 @@
         .object<jni$_.JString?>(const jni$_.$JString$NullableType$());
   }
 
+  static final _id_foo = _class.instanceMethodId(
+    r'foo',
+    r'()Ljava/lang/Object;',
+  );
+
+  static final _foo = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JniResult Function(
+                jni$_.Pointer<jni$_.Void>,
+                jni$_.JMethodIDPtr,
+              )>>('globalEnv_CallObjectMethod')
+      .asFunction<
+          jni$_.JniResult Function(
+            jni$_.Pointer<jni$_.Void>,
+            jni$_.JMethodIDPtr,
+          )>();
+
+  /// from: `synthetic public bridge java.lang.Object foo()`
+  /// The returned object must be released after use, by calling the [release] method.
+  jni$_.JObject? foo() {
+    return _foo(reference.pointer, _id_foo as jni$_.JMethodIDPtr)
+        .object<jni$_.JObject?>(const jni$_.$JObject$NullableType$());
+  }
+
   /// Maps a specific port to the implemented interface.
   static final core$_.Map<int, $DerivedInterface> _$impls = {};
   static jni$_.JObjectPtr _$invoke(
@@ -9836,6 +10629,14 @@
                 .toPointer() ??
             jni$_.nullptr;
       }
+      if ($d == r'foo()Ljava/lang/Object;') {
+        final $r = _$impls[$p]!.foo();
+        return ($r as jni$_.JObject?)
+                ?.as(const jni$_.$JObject$Type$())
+                .reference
+                .toPointer() ??
+            jni$_.nullptr;
+      }
     } catch (e) {
       return jni$_.ProtectedJniExtensions.newDartException(e);
     }
@@ -9881,21 +10682,30 @@
 abstract base mixin class $DerivedInterface {
   factory $DerivedInterface({
     required jni$_.JString? Function() foo,
+    required jni$_.JObject? Function() foo,
   }) = _$DerivedInterface;
 
   jni$_.JString? foo();
+  jni$_.JObject? foo();
 }
 
 final class _$DerivedInterface with $DerivedInterface {
   _$DerivedInterface({
     required jni$_.JString? Function() foo,
-  }) : _foo = foo;
+    required jni$_.JObject? Function() foo,
+  })  : _foo = foo,
+        _foo = foo;
 
   final jni$_.JString? Function() _foo;
+  final jni$_.JObject? Function() _foo;
 
   jni$_.JString? foo() {
     return _foo();
   }
+
+  jni$_.JObject? foo() {
+    return _foo();
+  }
 }
 
 final class $DerivedInterface$NullableType$
@@ -10383,7 +11193,7 @@
   /// from: `public void <init>(com.github.dart_lang.jnigen.annotations.Annotated<T, U, W> $outerClass, V object)`
   /// The returned object must be released after use, by calling the [release] method.
   factory Annotated$Nested(
-    Annotated<$T?, $U, $W> $outerClass,
+    Annotated<$T?, $U, $W> $$outerClass,
     $V? object, {
     jni$_.JType<$T>? T,
     jni$_.JType<$U>? U,
@@ -10391,21 +11201,21 @@
     required jni$_.JType<$V> V,
   }) {
     T ??= jni$_.lowestCommonSuperType([
-      ($outerClass.$type as $Annotated$Type$<core$_.dynamic, core$_.dynamic,
+      ($$outerClass.$type as $Annotated$Type$<core$_.dynamic, core$_.dynamic,
               core$_.dynamic>)
           .T,
     ]) as jni$_.JType<$T>;
     U ??= jni$_.lowestCommonSuperType([
-      ($outerClass.$type as $Annotated$Type$<core$_.dynamic, core$_.dynamic,
+      ($$outerClass.$type as $Annotated$Type$<core$_.dynamic, core$_.dynamic,
               core$_.dynamic>)
           .U,
     ]) as jni$_.JType<$U>;
     W ??= jni$_.lowestCommonSuperType([
-      ($outerClass.$type as $Annotated$Type$<core$_.dynamic, core$_.dynamic,
+      ($$outerClass.$type as $Annotated$Type$<core$_.dynamic, core$_.dynamic,
               core$_.dynamic>)
           .W,
     ]) as jni$_.JType<$W>;
-    final _$$outerClass = $outerClass.reference;
+    final _$$$outerClass = $$outerClass.reference;
     final _$object = object?.reference ?? jni$_.jNullReference;
     return Annotated$Nested<$T, $U, $W, $V>.fromReference(
         T,
@@ -10413,7 +11223,7 @@
         W,
         V,
         _new$(_class.reference.pointer, _id_new$ as jni$_.JMethodIDPtr,
-                _$$outerClass.pointer, _$object.pointer)
+                _$$$outerClass.pointer, _$object.pointer)
             .reference);
   }
 }
@@ -12589,6 +13399,57 @@
         .object<JsonSerializable$Case?>(
             const $JsonSerializable$Case$NullableType$());
   }
+
+  static final _id_new$ = _class.constructorId(
+    r'(Ljava/lang/String;I)V',
+  );
+
+  static final _new$ = jni$_.ProtectedJniExtensions.lookup<
+              jni$_.NativeFunction<
+                  jni$_.JniResult Function(
+                      jni$_.Pointer<jni$_.Void>,
+                      jni$_.JMethodIDPtr,
+                      jni$_
+                          .VarArgs<(jni$_.Pointer<jni$_.Void>, jni$_.Int32)>)>>(
+          'globalEnv_NewObject')
+      .asFunction<
+          jni$_.JniResult Function(jni$_.Pointer<jni$_.Void>,
+              jni$_.JMethodIDPtr, jni$_.Pointer<jni$_.Void>, int)>();
+
+  /// from: `private void <init>(java.lang.String string, int i)`
+  /// The returned object must be released after use, by calling the [release] method.
+  factory JsonSerializable$Case(
+    jni$_.JString? string,
+    int i,
+  ) {
+    final _$string = string?.reference ?? jni$_.jNullReference;
+    return JsonSerializable$Case.fromReference(_new$(_class.reference.pointer,
+            _id_new$ as jni$_.JMethodIDPtr, _$string.pointer, i)
+        .reference);
+  }
+
+  static final _id_$_clinit_ = _class.staticMethodId(
+    r'<clinit>',
+    r'()V',
+  );
+
+  static final _$_clinit_ = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JThrowablePtr Function(
+                jni$_.Pointer<jni$_.Void>,
+                jni$_.JMethodIDPtr,
+              )>>('globalEnv_CallStaticVoidMethod')
+      .asFunction<
+          jni$_.JThrowablePtr Function(
+            jni$_.Pointer<jni$_.Void>,
+            jni$_.JMethodIDPtr,
+          )>();
+
+  /// from: `static void <clinit>()`
+  static void $_clinit_() {
+    _$_clinit_(_class.reference.pointer, _id_$_clinit_ as jni$_.JMethodIDPtr)
+        .check();
+  }
 }
 
 final class $JsonSerializable$Case$NullableType$
@@ -13894,6 +14755,56 @@
         _new$(_class.reference.pointer, _id_new$ as jni$_.JMethodIDPtr)
             .reference);
   }
+
+  static final _id_foo$1 = _class.instanceMethodId(
+    r'foo',
+    r'()Lcom/github/dart_lang/jnigen/regressions/R693$Child;',
+  );
+
+  static final _foo$1 = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JniResult Function(
+                jni$_.Pointer<jni$_.Void>,
+                jni$_.JMethodIDPtr,
+              )>>('globalEnv_CallObjectMethod')
+      .asFunction<
+          jni$_.JniResult Function(
+            jni$_.Pointer<jni$_.Void>,
+            jni$_.JMethodIDPtr,
+          )>();
+
+  /// from: `com.github.dart_lang.jnigen.regressions.R693$Child foo()`
+  /// The returned object must be released after use, by calling the [release] method.
+  R693$Child? foo$1() {
+    return _foo$1(reference.pointer, _id_foo$1 as jni$_.JMethodIDPtr)
+        .object<R693$Child?>(const $R693$Child$NullableType$());
+  }
+
+  static final _id_foo = _class.instanceMethodId(
+    r'foo',
+    r'()Lcom/github/dart_lang/jnigen/regressions/R693;',
+  );
+
+  static final _foo = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JniResult Function(
+                jni$_.Pointer<jni$_.Void>,
+                jni$_.JMethodIDPtr,
+              )>>('globalEnv_CallObjectMethod')
+      .asFunction<
+          jni$_.JniResult Function(
+            jni$_.Pointer<jni$_.Void>,
+            jni$_.JMethodIDPtr,
+          )>();
+
+  /// from: `synthetic bridge com.github.dart_lang.jnigen.regressions.R693 foo()`
+  /// The returned object must be released after use, by calling the [release] method.
+  R693<jni$_.JObject?>? foo() {
+    return _foo(reference.pointer, _id_foo as jni$_.JMethodIDPtr)
+        .object<R693<jni$_.JObject?>?>(
+            const $R693$NullableType$<jni$_.JObject?>(
+                jni$_.$JObject$NullableType$()));
+  }
 }
 
 final class $R693$Child$NullableType$ extends jni$_.JType<R693$Child?> {
@@ -14037,6 +14948,30 @@
         _new$(_class.reference.pointer, _id_new$ as jni$_.JMethodIDPtr)
             .reference);
   }
+
+  static final _id_foo = _class.instanceMethodId(
+    r'foo',
+    r'()Lcom/github/dart_lang/jnigen/regressions/R693;',
+  );
+
+  static final _foo = jni$_.ProtectedJniExtensions.lookup<
+          jni$_.NativeFunction<
+              jni$_.JniResult Function(
+                jni$_.Pointer<jni$_.Void>,
+                jni$_.JMethodIDPtr,
+              )>>('globalEnv_CallObjectMethod')
+      .asFunction<
+          jni$_.JniResult Function(
+            jni$_.Pointer<jni$_.Void>,
+            jni$_.JMethodIDPtr,
+          )>();
+
+  /// from: `T foo()`
+  /// The returned object must be released after use, by calling the [release] method.
+  $T? foo() {
+    return _foo(reference.pointer, _id_foo as jni$_.JMethodIDPtr)
+        .object<$T?>(T.nullableType);
+  }
 }
 
 final class $R693$NullableType$<$T extends jni$_.JObject?>
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/BaseGenericInterface.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/BaseGenericInterface.java
index 6cfce54..9b3531f 100644
--- a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/BaseGenericInterface.java
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/BaseGenericInterface.java
@@ -1,3 +1,7 @@
+// Copyright (c) 2025, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
 package com.github.dart_lang.jnigen.inheritance;
 
 public interface BaseGenericInterface<T> {
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/BaseInterface.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/BaseInterface.java
index b035ddd..1269d07 100644
--- a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/BaseInterface.java
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/BaseInterface.java
@@ -1,3 +1,7 @@
+// Copyright (c) 2025, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
 package com.github.dart_lang.jnigen.inheritance;
 
 public interface BaseInterface {
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/DerivedInterface.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/DerivedInterface.java
index 4afebd5..bfee1fd 100644
--- a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/DerivedInterface.java
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/DerivedInterface.java
@@ -1,3 +1,7 @@
+// Copyright (c) 2025, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
 package com.github.dart_lang.jnigen.inheritance;
 
 public interface DerivedInterface extends BaseGenericInterface<String>, BaseInterface {
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/InheritedFromMyInterface.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/InheritedFromMyInterface.java
index a8bbe2e..80c4831 100644
--- a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/InheritedFromMyInterface.java
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/InheritedFromMyInterface.java
@@ -1,3 +1,7 @@
+// Copyright (c) 2025, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
 package com.github.dart_lang.jnigen.interfaces;
 
 public interface InheritedFromMyInterface extends MyInterface<String> {}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/InheritedFromMyRunnable.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/InheritedFromMyRunnable.java
index 81cc74f..31b6732 100644
--- a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/InheritedFromMyRunnable.java
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/InheritedFromMyRunnable.java
@@ -1,3 +1,7 @@
+// Copyright (c) 2025, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
 package com.github.dart_lang.jnigen.interfaces;
 
 public interface InheritedFromMyRunnable extends MyRunnable {}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/overrides/Duck.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/overrides/Duck.java
new file mode 100644
index 0000000..6433a67
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/overrides/Duck.java
@@ -0,0 +1,7 @@
+// Copyright (c) 2025, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.overrides;
+
+public class Duck {}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/overrides/Ducking.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/overrides/Ducking.java
new file mode 100644
index 0000000..0388d55
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/overrides/Ducking.java
@@ -0,0 +1,9 @@
+// Copyright (c) 2025, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.overrides;
+
+public interface Ducking {
+  void duck();
+}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/overrides/DuckingPlayer.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/overrides/DuckingPlayer.java
new file mode 100644
index 0000000..6e9106c
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/overrides/DuckingPlayer.java
@@ -0,0 +1,7 @@
+// Copyright (c) 2025, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.overrides;
+
+public class DuckingPlayer extends Player implements Ducking, JustAChillDuck {}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/overrides/JustAChillDuck.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/overrides/JustAChillDuck.java
new file mode 100644
index 0000000..24a66b4
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/overrides/JustAChillDuck.java
@@ -0,0 +1,9 @@
+// Copyright (c) 2025, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.overrides;
+
+public interface JustAChillDuck {
+  void duck();
+}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/overrides/Player.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/overrides/Player.java
new file mode 100644
index 0000000..c467952
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/overrides/Player.java
@@ -0,0 +1,13 @@
+// Copyright (c) 2025, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.overrides;
+
+public class Player {
+  // Player's personal duck!
+  public Duck duck;
+
+  // Lower your head!
+  public void duck() {}
+}
diff --git a/pkgs/jnigen/test/user_visitor_test.dart b/pkgs/jnigen/test/user_visitor_test.dart
deleted file mode 100644
index 1a62166..0000000
--- a/pkgs/jnigen/test/user_visitor_test.dart
+++ /dev/null
@@ -1,203 +0,0 @@
-// Copyright (c) 2024, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:jnigen/jnigen.dart' as jnigen;
-import 'package:jnigen/src/bindings/linker.dart';
-import 'package:jnigen/src/bindings/renamer.dart';
-import 'package:jnigen/src/elements/elements.dart' as ast;
-import 'package:jnigen/src/elements/j_elements.dart';
-import 'package:test/test.dart';
-
-extension on Iterable<ast.Method> {
-  List<bool> get isExcludedValues =>
-      map((c) => c.userDefinedIsExcluded).toList();
-}
-
-extension on Iterable<ast.Field> {
-  List<bool> get isExcludedValues => map((c) => c.isExcluded).toList();
-}
-
-extension on Iterable<ast.Method> {
-  List<String> get finalNames => map((m) => m.finalName).toList();
-}
-
-extension on Iterable<ast.Param> {
-  List<String> get finalNames => map((p) => p.finalName).toList();
-}
-
-extension on Iterable<ast.Field> {
-  List<String> get finalNames => map((f) => f.finalName).toList();
-}
-
-// This is customizable by the user
-class UserExcluder extends Visitor {
-  @override
-  void visitClass(ClassDecl c) {
-    if (c.binaryName.contains('y')) {
-      c.isExcluded = true;
-    }
-  }
-
-  @override
-  void visitMethod(Method method) {
-    if (method.name == 'Bar') {
-      method.isExcluded = true;
-    }
-  }
-
-  @override
-  void visitField(Field field) {
-    if (field.name == 'Bar') {
-      field.isExcluded = true;
-    }
-  }
-}
-
-// This is customizable by the user
-class UserRenamer extends Visitor {
-  @override
-  void visitClass(ClassDecl c) {
-    if (c.originalName.contains('Foo')) {
-      c.name = c.originalName.replaceAll('Foo', 'Bar');
-    }
-  }
-
-  @override
-  void visitMethod(Method method) {
-    if (method.originalName.contains('Foo')) {
-      method.name = method.originalName.replaceAll('Foo', 'Bar');
-    }
-    if (method.isConstructor) {
-      method.name = 'constructor';
-    }
-  }
-
-  @override
-  void visitField(Field field) {
-    if (field.originalName.contains('Foo')) {
-      field.name = field.originalName.replaceAll('Foo', 'Bar');
-    }
-  }
-
-  @override
-  void visitParam(Param parameter) {
-    if (parameter.originalName.contains('Foo')) {
-      parameter.name = parameter.originalName.replaceAll('Foo', 'Bar');
-    }
-  }
-}
-
-Future<void> rename(ast.Classes classes) async {
-  final config = jnigen.Config(
-      outputConfig: jnigen.OutputConfig(
-        dartConfig: jnigen.DartCodeOutputConfig(
-          path: Uri.file('test.dart'),
-          structure: jnigen.OutputStructure.singleFile,
-        ),
-      ),
-      classes: []);
-  await classes.accept(Linker(config));
-  classes.accept(Renamer(config));
-}
-
-void main() {
-  test('Exclude something using the user excluder, Simple AST', () async {
-    final classes = ast.Classes({
-      'Foo': ast.ClassDecl(
-        binaryName: 'Foo',
-        declKind: ast.DeclKind.classKind,
-        superclass: ast.DeclaredType.object,
-        methods: [
-          ast.Method(name: 'foo', returnType: ast.DeclaredType.object),
-          ast.Method(name: 'Bar', returnType: ast.DeclaredType.object),
-          ast.Method(name: 'foo1', returnType: ast.DeclaredType.object),
-          ast.Method(name: 'Bar', returnType: ast.DeclaredType.object),
-        ],
-        fields: [
-          ast.Field(name: 'foo', type: ast.DeclaredType.object),
-          ast.Field(name: 'Bar', type: ast.DeclaredType.object),
-          ast.Field(name: 'foo1', type: ast.DeclaredType.object),
-          ast.Field(name: 'Bar', type: ast.DeclaredType.object),
-        ],
-      ),
-      'y.Foo': ast.ClassDecl(
-          binaryName: 'y.Foo',
-          declKind: ast.DeclKind.classKind,
-          superclass: ast.DeclaredType.object,
-          methods: [
-            ast.Method(name: 'foo', returnType: ast.DeclaredType.object),
-            ast.Method(name: 'Bar', returnType: ast.DeclaredType.object),
-          ],
-          fields: [
-            ast.Field(name: 'foo', type: ast.DeclaredType.object),
-            ast.Field(name: 'Bar', type: ast.DeclaredType.object),
-          ]),
-    });
-
-    final simpleClasses = Classes(classes);
-    simpleClasses.accept(UserExcluder());
-
-    expect(classes.decls['y.Foo']?.isExcluded, true);
-    expect(classes.decls['Foo']?.isExcluded, false);
-
-    expect(classes.decls['Foo']?.fields.isExcludedValues,
-        [false, true, false, true]);
-    expect(classes.decls['Foo']?.methods.isExcludedValues,
-        [false, true, false, true]);
-  });
-
-  test('Rename classes, fields, methods and params using the user renamer',
-      () async {
-    final classes = ast.Classes({
-      'Foo': ast.ClassDecl(
-        binaryName: 'Foo',
-        declKind: ast.DeclKind.classKind,
-        superclass: ast.DeclaredType.object,
-        methods: [
-          ast.Method(name: 'Foo', returnType: ast.DeclaredType.object),
-          ast.Method(name: 'Foo', returnType: ast.DeclaredType.object),
-          ast.Method(name: 'Foo1', returnType: ast.DeclaredType.object),
-          ast.Method(name: 'Foo1', returnType: ast.DeclaredType.object),
-        ],
-        fields: [
-          ast.Field(name: 'Foo', type: ast.DeclaredType.object),
-          ast.Field(name: 'Foo', type: ast.DeclaredType.object),
-          ast.Field(name: 'Foo1', type: ast.DeclaredType.object),
-          ast.Field(name: 'Foo1', type: ast.DeclaredType.object),
-        ],
-      ),
-      'y.Foo': ast.ClassDecl(
-        binaryName: 'y.Foo',
-        declKind: ast.DeclKind.classKind,
-        superclass: ast.DeclaredType.object,
-        methods: [
-          ast.Method(name: 'Foo', returnType: ast.DeclaredType.object, params: [
-            ast.Param(name: 'Foo', type: ast.DeclaredType.object),
-            ast.Param(name: 'Foo1', type: ast.DeclaredType.object),
-          ]),
-          ast.Method(name: '<init>', returnType: ast.DeclaredType.object)
-        ],
-      ),
-    });
-
-    final simpleClasses = Classes(classes);
-    simpleClasses.accept(UserRenamer());
-
-    await rename(classes);
-
-    expect(classes.decls['Foo']?.finalName, 'Bar');
-    expect(classes.decls['y.Foo']?.finalName, r'Bar$1');
-
-    expect(classes.decls['Foo']?.fields.finalNames,
-        ['Bar', r'Bar$1', 'Bar1', r'Bar1$1']);
-
-    expect(classes.decls['Foo']?.methods.finalNames,
-        [r'Bar$2', r'Bar$3', r'Bar1$2', r'Bar1$3']);
-
-    expect(classes.decls['y.Foo']?.methods.finalNames, [r'Bar', 'constructor']);
-
-    expect(classes.decls['y.Foo']?.methods.first.params.finalNames,
-        ['Bar', 'Bar1']);
-  });
-}