I hit another problem with converted dlls. I was able to fix it locally with ChatGPT and wanted to share the fix here.
Problem
When IKVM generates stubs for converted assemblies, class-valued annotation metadata can contain a .NET assembly-qualified type name instead of a valid Java descriptor.
For example, metadata intended to contain:
Ljava/lang/Thread;
may instead contain:
Ljava/lang/Thread, IKVM.Java, Version=..., Culture=..., PublicKeyToken=...;
The comma and assembly metadata make the generated descriptor invalid.
Cause
StubGenerator encodes class-valued annotation elements directly from the stored type string. Some of these strings originate from Type.AssemblyQualifiedName, so they include .NET assembly metadata.
Required changes
In src/IKVM.Runtime/StubGen/StubGenerator.cs, add a helper that detects assembly-qualified descriptors, resolves the underlying IKVM Java class, and returns its canonical Java descriptor:
static string DecodeTypeName(string typeName)
{
#if !FIRST_PASS && !EXPORTER
int index = typeName.IndexOf(',');
if (index > 0)
{
// Resolve an assembly-qualified .NET type name back to
// its canonical Java class descriptor.
try
{
typeName =
"L" +
java.lang.Class
.forName(typeName.Substring(1, typeName.Length - 2).Replace('/', '.'))
.getName()
.Replace('.', '/') +
";";
}
catch
{
// Preserve the original value if it cannot be resolved.
}
}
#endif
return typeName;
}
For FIRST_PASS and EXPORTER builds, the helper can remain a no-op if required by the existing conditional compilation structure:
#if FIRST_PASS || EXPORTER
static string DecodeTypeName(string typeName) => typeName;
#endif
Pass type descriptors through DecodeTypeName before adding them to the constant pool.
For object-array annotation data, update the class, enum, and nested-annotation cases:
encoder.Enum(
builder.Constants.GetOrAddUtf8(DecodeTypeName((string)v[1])),
builder.Constants.GetOrAddUtf8((string)v[2]));
encoder.Class(
builder.Constants.GetOrAddUtf8(DecodeTypeName((string)v[1])));
e.Annotation(
builder.Constants.GetOrAddUtf8(DecodeTypeName((string)v[1])),
e2 =>
{
// Existing element encoding
});
Also update the CustomAttributeTypedArgument TAG_CLASS path:
encoder.Class(
builder.Constants.GetOrAddUtf8(
DecodeTypeName((string)data[1].Value)));
Expected result
Assembly-qualified .NET names are normalized before being written to Java annotation metadata. Generated output contains valid descriptors such as Ljava/lang/Thread;, without the trailing comma, assembly name, version, culture, or public-key token.
I hit another problem with converted dlls. I was able to fix it locally with ChatGPT and wanted to share the fix here.
Problem
When IKVM generates stubs for converted assemblies, class-valued annotation metadata can contain a .NET assembly-qualified type name instead of a valid Java descriptor.
For example, metadata intended to contain:
Ljava/lang/Thread;may instead contain:
Ljava/lang/Thread, IKVM.Java, Version=..., Culture=..., PublicKeyToken=...;The comma and assembly metadata make the generated descriptor invalid.
Cause
StubGenerator encodes class-valued annotation elements directly from the stored type string. Some of these strings originate from Type.AssemblyQualifiedName, so they include .NET assembly metadata.
Required changes
In src/IKVM.Runtime/StubGen/StubGenerator.cs, add a helper that detects assembly-qualified descriptors, resolves the underlying IKVM Java class, and returns its canonical Java descriptor:
For FIRST_PASS and EXPORTER builds, the helper can remain a no-op if required by the existing conditional compilation structure:
Pass type descriptors through DecodeTypeName before adding them to the constant pool.
For object-array annotation data, update the class, enum, and nested-annotation cases:
Also update the CustomAttributeTypedArgument TAG_CLASS path:
Expected result
Assembly-qualified .NET names are normalized before being written to Java annotation metadata. Generated output contains valid descriptors such as Ljava/lang/Thread;, without the trailing comma, assembly name, version, culture, or public-key token.