Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MainClass clinit does not initailize other classes in correct order #897

Open
taylortails opened this issue Mar 23, 2024 · 4 comments
Open

Comments

@taylortails
Copy link

version 0.10.0-dev-10

When I run my generated javascript I get this error:

TypeError: Cannot read property '$clone0' of null
	at <js> jus_Collector$Characteristics_values(target\generated\js\teavm\model.mjs:22749:1000149-1000193)
	at <js> otp_Platform_getEnumConstants(target\generated\js\teavm\model.mjs:3021:177633-177640)
	at <js> otp_Platform_getEnumConstants(target\generated\js\teavm\model.mjs:3025:177694-177729)
	at <js> ju_GenericEnumSet_getConstants(target\generated\js\teavm\model.mjs:24674:1070248-1070292)
	at <js> jus_Collector_of0(target\generated\js\teavm\model.mjs:22777:1001520-1001589)
	at <js> jus_Collector_of(target\generated\js\teavm\model.mjs:22771:1001121-1001225)
	at <js> jus_Collectors_toCollection(target\generated\js\teavm\model.mjs:21341:938512-938688)
	at <js> jus_Collectors_toSet(target\generated\js\teavm\model.mjs:21347:938850-938914)
	at <js> chdtlmu_ModelBuilder_getImpls(target\generated\js\teavm\model.mjs:6890:367818-367839)
	at <js> chdtlmi_TypedReaderImpl__clinit_(target\generated\js\teavm\model.mjs:48486:2033785-2033815)
	at org.graalvm.polyglot.Context.eval(Context.java:402)

This is happing because my class' clinit is called before Characteristics__clinit is called

chdtlmj_Entrypoint__clinit_ = () => {
...
    chdtlmi_TypedReaderImpl__clinit_();
...
    jus_Collector$Characteristics__clinit_();

I can workaround by manually reording code in the generated javascript, or re-write my java code to use a code path that doesnt require this code to be initialized.

Regards.

@konsoletyper
Copy link
Owner

Can you provide any details on your code? I'm not interested in JVM version or operating system. What I'm interested in is the Java code you are trying to convert to JavaScript. It would be best if you could write a self-contained example that reproduces the issue.

As for workaround, try placing something like Class.forName("java.util.stream.Collector$Characteristics") in Entrypoint's static initializer.

@konsoletyper
Copy link
Owner

I tried with trivial example like this:

static {
    System.out.println(Stream.of(1, 2, 3).collect(Collectors.toSet()));
}

And what I get in entry point's <clinit> method is following:

    jl_String__clinit_();
    jl_Integer__clinit_();
    jl_Character__clinit_();
    jnci_UTF8Charset__clinit_();
    jus_Collector$Characteristics__clinit_();
},

You can notice that calling initializer does not present in this list. This is expected, since it calls native method Platform.getEnumConstants, for which TeaVM can't establish any relation, so this initializer is marked as 'dynamic', which means that it won't be statically initialized in entry point, but rather be dynamically initialized on first use. Why this does not happen in your case, I don't know since have not idea what do other methods (like ModelBuilder.getImpl and perhaps others) do.

@taylortails
Copy link
Author

thanks for spending the time trying to reproduce, yes - I had trouble trying to produce a simple example that reproduces the issue.. I'll try again soon, my best guess currently is that if you export multiple methods they'd each have different initialization order - hence combining them needs to be done carefully. If this is true it would make sense because exporting multiple methods is new.

@konsoletyper
Copy link
Owner

If it's possible, you can post your original project. In case it's closed-source, you can reach me directly in Gitter and we'll discuss terms.

my best guess currently is that if you export multiple methods they'd each have different initialization order - hence combining them needs to be done carefully

Your guess is wrong. The order of initializers does not depend on 'main' method or other entry points, but rather from relation of static initializers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants