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

Catch IAE when Gradle error getLocation cannot be called. #5270

Merged
merged 1 commit into from
Jan 12, 2023

Conversation

lkishalmi
Copy link
Contributor

I've bumped into this one today:

java.lang.IllegalArgumentException: object is not an instance of declaring class
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.netbeans.modules.gradle.loaders.LegacyProjectLoader.getLocation(LegacyProjectLoader.java:380)

Couldn't really know how to reproduce. I was fiddling with old Gradle versions with the new tooling.

The fix is trivial though...

@lkishalmi lkishalmi added the Gradle [ci] enable "build tools" tests label Jan 11, 2023
@lkishalmi lkishalmi added this to the NB17 milestone Jan 11, 2023
Comment on lines 383 to 374
return null;
} catch (IllegalArgumentException iae) {
LOG.log(Level.FINE,"Trying to get location from an exception, that has no location property: " + locationAwareEx.getClass().getName());
}
return null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the problem might be deeper than this. The method accepts throwable but expects it to be LocationAwareException. If someone would call it with the wrong exception type

            if (locationAccessor == null) {
                locationAccessor = locationAwareEx.getClass().getMethod("getLocation"); // NOI18N
            }

would intitialize the field wrong if it happens to have that method, and all subsequent calls will fail or do really weird things.

I personally am not a fan of Throwable usage, since it is in 99% of all cases not something you should be catching.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I think it's a tradeoff we need to pay when we try to cover multiple versions at once. My mind could trick me, but some exceptions had getLocation methods even before LocationAwareException was introduced.

This is just some heuristic, trying to figure out what's behind a Gradle build failure. If we can get a location out of that we display it as an editor hint on the source code.

Well, if the heuristic does not work we just shall let it go...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but doesn't the Method field has to fit to the right class? If this method is supposed to be as generic as possible and work for all exceptions which have a getLocation method, I don't think it should be cached as field. It should be checked if that exception has getLocation on every invocation:

            Method locationAccessor = locationAwareEx.getClass().getMethod("getLocation"); // NOI18N
            return (String)locationAccessor.invoke(locationAwareEx);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this illustrates the issue:

        Integer five = 5;
        Double pi = Math.PI;
        
        Method stringAccessor =  five.getClass().getMethod("toString");
        System.out.println(stringAccessor.invoke(pi));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Point taken. Haven't really checked what's in the try block. Thanks!

@lkishalmi lkishalmi force-pushed the old-gradle-not-location-aware branch from 10a2bff to b367560 Compare January 11, 2023 06:47
@lkishalmi lkishalmi force-pushed the old-gradle-not-location-aware branch from b367560 to 00d5d23 Compare January 11, 2023 07:07
Copy link
Member

@mbien mbien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me

@sdedic
Copy link
Member

sdedic commented Jan 11, 2023

Let me try a different fix ... I've cached the accessor so that the reflective access is not that slow; but it should be easy to check for instanceof LocationAwareException. It seems that I might do a completely wrong thing with this reflective stuff, as the LocationAwareEx type is in the same place since Gradle 3.1 or even more ... give me 24hrs to check, thanks.

@mbien mbien added the do not merge Don't merge this PR, it is not ready or just demonstration purposes. label Jan 11, 2023
@mbien
Copy link
Member

mbien commented Jan 11, 2023

added do not merge label so that nobody merges by accident

@lkishalmi
Copy link
Contributor Author

@sdedic Take your time!

Just would like to add, that it's fine not to cache the Method accessor here. This is on a critical path.

@sdedic
Copy link
Member

sdedic commented Jan 12, 2023

Ouch ! No caching is possible, in fact. During debugging, I've realized (only now) that the Tooling API seems to load classes for the deserialized data using a throwaway classloader , so Classes from 2 project loads are not assignable at all, even though they represent the same type.

@mbien mbien removed the do not merge Don't merge this PR, it is not ready or just demonstration purposes. label Jan 12, 2023
@mbien
Copy link
Member

mbien commented Jan 12, 2023

@sdedic thanks a lot for checking! Reflection is super fast anyway these days - I don't think much is lost there.

@lkishalmi lkishalmi merged commit b1192ba into apache:master Jan 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Gradle [ci] enable "build tools" tests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants