jOOQ / jOOR

jOOR - Fluent Reflection in Java jOOR is a very simple fluent API that gives access to your Java Class structures in a more intuitive way. The JDK's reflection APIs are hard and verbose to use. Other languages have much simpler constructs to access type meta information at runtime. Let us make Java reflection better.
http://www.jooq.org/products
Apache License 2.0
2.8k stars 377 forks source link

Provide option for preventing duplicate definition of classes when compiling multiple classes present in sourcepath and classpath #89

Closed mellster2012 closed 4 years ago

mellster2012 commented 4 years ago

…mpiling multiple source files and their dependencies

mellster2012 commented 4 years ago

Sure I'll add the option to CompileOptions and restore the white space. The use case is that I have a source path for java source files and am running the compiler on it. All of the java sources within the source path are picked up by the compiler and when multiple of those classes depend on others within the same source path the compiler will always recompile and Reflect's ClassFileManager will end up re-defining those classes, causing a Linkage error (the javac compiler option -implicit is too coarse grained to make it work without these changes). I can probably add a test simulating my use case as well.

mellster2012 commented 4 years ago

Updated for the requested changes. It's not a javac option that can be passed through so I moved it into CompileOptions but outside of the String options passed onto javac. Let me know if you like a test as well.

lukaseder commented 4 years ago

Thanks for your explanation. I'm not quite sure if I understand the problem yet...

I can probably add a test simulating my use case as well.

Yes, I'd appreciate that! Thanks again

mellster2012 commented 4 years ago

@lukaseder see the corrected use case added as a test. Basically source files take precedence and get recompiled when present in source and classpath, which will cause class redefinition and this can be avoided with the additional flag.

lukaseder commented 4 years ago

Thanks for the ping. I had seen your test case and was assuming you'd follow up with further explanations.

I'm afraid that from the test case alone, I still don't understand what problem you're trying to solve here. Your test case doesn't fail without the patch you've offered:


    @Test
    public void testSkipLoadedClasses() throws Exception {
        CompileOptions options = new CompileOptions().options("-sourcepath", "src/test/java/").options("-classpath", "src/test/java");
        // options.skipLoadedClasses(true);
        Reflect.compile("TestHierarchicalMethodsBase", new String(java.nio.file.Files.readAllBytes(new File("src/test/java/org/joor/test/TestHierarchicalMethodsBase.java").toPath())), options);
        Reflect.compile("TestHierarchicalMethodsSubclass", new String(java.nio.file.Files.readAllBytes(new File("src/test/java/org/joor/test/TestHierarchicalMethodsSubclass.java").toPath())), options);
    }

I'll be willing to spend more time on this. However, I would really need a very clear problem description, first. Perhaps, we can start over with an issue and without a PR? I feel we're already deep down in some solution space when in fact I still haven't understood the underlying problem (i.e. a case of the XYProblem, as happens often when a PR is offered before a problem description is expressed).

mellster2012 commented 4 years ago

Hmm the test fails for me without the option enabled (see below). I agree it's an edge case although it happened in a real-life project, given classes that exist both in the classpath and the sourcepath while all classes in the sourcepath need to be (re-)compiled. It's not critical though, maybe someone else will encounter this at a later point at which we could revisit. Thanks for reviewing it!

org.joor.ReflectException: java.lang.reflect.InvocationTargetException at org.joor.Reflect.on(Reflect.java:906) at org.joor.Reflect.call(Reflect.java:581) at org.joor.Compile.lambda$0(Compile.java:107) at org.joor.Compile$ClassFileManager.loadAndReturnMainClass(Compile.java:251) at org.joor.Compile.compile(Compile.java:106) at org.joor.Reflect.compile(Reflect.java:103) at org.joor.test.CompileTest.testSkipLoadedClasses(CompileTest.java:187) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209) Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.joor.Reflect.on(Reflect.java:902) ... 29 more Caused by: java.lang.LinkageError: loader (instance of sun/misc/Launcher$AppClassLoader): attempted duplicate class definition for name: "org/joor/test/TestHierarchicalMethodsBase" at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:763) at java.lang.ClassLoader.defineClass(ClassLoader.java:642) ... 34 more