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

Classes loaded by inconsistent loaders (visible only in test) #39

Open
paul-bennett opened this issue Apr 11, 2023 · 5 comments
Open

Classes loaded by inconsistent loaders (visible only in test) #39

paul-bennett opened this issue Apr 11, 2023 · 5 comments
Labels
bug Something isn't working help wanted Extra attention is needed

Comments

@paul-bennett
Copy link
Owner

This test from README.md fails if it's run by TestSamples from COVERAGE.md:

$ juggle -j build/libs/testLib.jar -r com.angellane.juggle.testinput.lib.Lib -a package
public static com.angellane.juggle.testinput.lib.Lib com.angellane.juggle.testinput.lib.Lib.libFactory()
com.angellane.juggle.testinput.lib.Lib.<init>()
$

Presumably this is related to the way TestSamples invokes main() multiple times in the same JVM process, but I'm not entirely sure what's happening.

Symptoms are that the test fails, having emitted no output whatsoever.

@paul-bennett
Copy link
Owner Author

paul-bennett commented Apr 12, 2023

Further evidence:

  • Swapping the order of the files README.md and COVERAGE.md in TestSamples causes the test to fail to pass in the first file in which it's encountered, but not the second. Adding it to REGRESSIONS.md causes it to fail there too (while continuing to pass in the first file).
  • Copying the same test in README.md causes it to fail on all but the first occurrence in the file.
  • Duplicates of the other -j test that's in README.md all pass
  • Moving the test around in the file doesn't make things better or worse

Changing CandidateMember.matchesThrows to:

    public boolean matchesReturn(Class<?> queryReturnType) {
        if (queryReturnType.getName().equals(returnType.getName())
            && !queryReturnType.getClassLoader().equals(returnType.getClassLoader()))
            System.err.println("ClassLoader mismatch for " + returnType.getName());

        return queryReturnType.getName().equals(returnType.getName()) ||
            isTypeCompatibleForAssignment(queryReturnType, returnType);
    }

and setting a breakpoint on the println reveals that on the second run of the test, we get to the point where the declaring class of the candidate member is equivalent (but not equal) to returnType, but they're not the same object and they've been loaded by different ClassLoaders. This means the isTypeCompatibleForAssignment test fails.

The modified return statement here makes this specific test pass due to the additional check for name equality, but isn't the right solution (because we need to go beyond name matches).

@paul-bennett
Copy link
Owner Author

Things that haven't worked...

  • Adding Thread.sleep(10000) in TestSamples after returning from main
  • Adding System.gc() at the same point

I've a strong sense that the classes (and the ClassLoader) from one run aren't completely flushed before the next run, and that for some reason those classes are obtained during the command-line parameter processing but not during the execution phase of subsequent runs.

@paul-bennett
Copy link
Owner Author

This problem might be caused by the delegation model of the standard ClassLoaders. Out-of-the-box, these classes delegate to their parent ClassLoader, and only load the class themselves if the parent hasn't already loaded it. I suspect that in practice some of our custom classes are loaded by the system class loader and these are getting muddled with those loaded by the ResolvingURLClassLoader.

Is it possible to force our subclass to always load all JAR and Module classes? There might be a performance impact, but it would at least allow us to force all classes into the same loader (and therefore not have the observed problem where types from different loaders were compared).

@paul-bennett paul-bennett changed the title Test fails in COVERAGE.md but not README.md Classes loaded by inconsistent loaders (visible only in test) May 3, 2023
@paul-bennett paul-bennett added bug Something isn't working help wanted Extra attention is needed labels May 9, 2023
@paul-bennett
Copy link
Owner Author

Perhaps a new ClassLoader that, ...

  • Remembers which classes it has loaded directly
  • Returns an already loaded class if requested again
  • If not loaded, tries to find the byte code in specified URIs and loads from there
  • Otherwise (i.e. if not found in URIs), delegates to parent

@paul-bennett
Copy link
Owner Author

I've also hit upon this issue while writing tests for issue #43. After fixing, check for disabled tests in the .md files.

@paul-bennett paul-bennett transferred this issue from another repository Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

1 participant