Bytecoder icon indicating copy to clipboard operation
Bytecoder copied to clipboard

Limitations reflection apis

Open CoenRijsdijk opened this issue 5 years ago • 10 comments

Related to #344 We are currently working on further implementing LibGDX in our backend. LibGdx uses reflection, arrays and generics together.

We ran into some problems about missing methods, but we could implement them by ourselves. Refers to commit: https://github.com/squins/Bytecoder/commit/464f287a1aae85362063d3f5a100e77084f82f91

A issue research branch is available where we researched this: https://github.com/squins/Bytecoder/tree/libgdx-reflection-requirements

We encountered some missing methods and collected them in a main class.

How hard would it be to implement them?

We have some questions about TClass:

  • why is @EmulatedByRuntime used with getName, does this have to do with the AOT compiler?
  • why is @EmulatedByRuntime not used for getComponentName?

Could you document Bytecoder annotations, for example @EmulatedByRuntime, to understand how to adapt with Bytecoder?

CoenRijsdijk avatar Dec 09 '20 14:12 CoenRijsdijk

  • Reflective field access can be implemented, see #344
  • Typed arrays are tricky, and are also not supported by the Bytecoder runtime. Internally a String[] is treatened as Object[],and no further type checking is processed
  • Annotations will maybe never be supported for reflective access.

My bet is the libGDX JSON unmarshaller depends a lot on Reflection API. So we either have to support the full reflection API, replace the unmarshaller, or provide a custom implementation replacing ClassReflection and ArrayReflection on a per project basis, with hard coded classes etc. Maybe this can be done by a code generator.

mirkosertic avatar Jan 04 '21 15:01 mirkosertic

Good news! I've merged the first implementation of reflection API support for the Bytecoder JavaScript backend. Please take a look at https://github.com/mirkosertic/Bytecoder/blob/master/core/src/test/java/de/mirkosertic/bytecoder/core/ReflectionTest.java to see the supported APIs and usecases.

mirkosertic avatar Jan 12 '21 11:01 mirkosertic

@mirkosertic Great! Thanks a lot!

If I want to run the ReflectionTest, what is the best way to do this? What I tried earlier:

  • mvn test -Dtest=ReflectionTest, I waited for 10 minutes and it keeps giving me compile feedback in the output screen, so how to run it properly?
  • Just run the test, but since we are using Java 8, when we imported Bytecoder, an error appears:

image

would it be solved if we use java 14/15?

CoenRijsdijk avatar Jan 13 '21 10:01 CoenRijsdijk

I am using OpenJDK8 here, IntelliJ as IDE. Basically rebuild the project and run the ReflectionTest class should do the trick. Please make sure the jaba8-compile Maven profile is active. The mentioned error is maybe caused by other active profiles that add the compiler flags, which are only supported in Java9+

mirkosertic avatar Jan 13 '21 11:01 mirkosertic

Hi Mirko, thanks for the work you've done! Really huge amount 👍

We have tried it out in our branch, see: https://github.com/squins/Bytecoder/tree/issue-research

Somehow the ReflectionTest is passing, but in our Main class it is not working. Maybe we have something wrongly configured in bytecoder-maven-plugin in the pom.xml?

keesvandieren avatar Jan 15 '21 20:01 keesvandieren

Hey!

I investigated your example, and I see the problem!

The ATO compiler does currently only include fields in the reflection field list which are statically referenced somewhere in the scanned dependency tree of linked classes. Because "staticField" is only referenced by reflection, and not by explicit JVM bytecode instructions, it is not included in the list of linked fields, and hence not included into the generated reflection metadata.

mirkosertic avatar Jan 22 '21 14:01 mirkosertic

I've pushed some fixes to the master branch. Would you please rebase your branch and give it a try? Also, please add the reflection configuration file bytecoder-reflection.json to the root of your classpath (src/main/resources) with the following content:

{
  "com.example.Main$BaseClass": {
    "enableClassForName": true
  },
  "com.example.Main$ReflectionTarget": {
    "enableClassForName": true
  },
  "com.example.MyClassWithField": {
    "enableClassForName": true
  }
}

mirkosertic avatar Jan 25 '21 11:01 mirkosertic

Thanks! It works fine!

Unfortunately I forgot to report this, we can fix it locally ofcourse (not the right way), but could you implement it next release? image

CoenRijsdijk avatar Jan 26 '21 15:01 CoenRijsdijk

Oops and another 😅 image

CoenRijsdijk avatar Jan 26 '21 15:01 CoenRijsdijk

I have 2 more bugs, hope you can fix it 😃, thanks in advance! image (1)

image (4)

CoenRijsdijk avatar Jan 27 '21 22:01 CoenRijsdijk