Skip to content

8199149: Improve the exception message thrown by VarHandle of unsupported operation #14928

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

Closed
wants to merge 5 commits into from

Conversation

mlchung
Copy link
Member

@mlchung mlchung commented Jul 19, 2023

VarForm::getMemberName currently throws UOE with no information if the requested access mode is unsupported. To provide the var handle information, move the access mode check to VarHandle so that the exception message can include the var handle information. Changes include:

  1. change VarHandle::checkAccessModeThenIsDirect to check if the access mode is unsupported. This check is only needed for direct var handle.
  2. change VarHandle::getMethodHandleUncached to call getMemberNameOrNull and throw UOE with an informative exception message if the access mode is unsupported

The error message looks like:

java.lang.UnsupportedOperationException: compareAndSet is not supported for VarHandle[varType=java.lang.String, coord=[class Foo$Goo]]

Progress

  • Change must be properly reviewed (1 review required, with at least 1 Reviewer)
  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue

Issue

  • JDK-8199149: Improve the exception message thrown by VarHandle of unsupported operation (Enhancement - P3)

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/14928/head:pull/14928
$ git checkout pull/14928

Update a local copy of the PR:
$ git checkout pull/14928
$ git pull https://git.openjdk.org/jdk.git pull/14928/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 14928

View PR using the GUI difftool:
$ git pr show -t 14928

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/14928.diff

Webrev

Link to Webrev Comment

@bridgekeeper
Copy link

bridgekeeper bot commented Jul 19, 2023

👋 Welcome back mchung! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk openjdk bot added the rfr Pull request is ready for review label Jul 19, 2023
@openjdk
Copy link

openjdk bot commented Jul 19, 2023

@mlchung The following label will be automatically applied to this pull request:

  • core-libs

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command.

@openjdk openjdk bot added the core-libs core-libs-dev@openjdk.org label Jul 19, 2023
@mlbridge
Copy link

mlbridge bot commented Jul 19, 2023

Webrevs

}

static AccessMode valueFromOrdinal(int mode) {
return modeToAccessMode.get(mode);
Copy link
Member

Choose a reason for hiding this comment

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

Can't this be simplified to AccessMode.values()[mode] since this is only rarely used in the exception logic?

If we do need a cache, I would recommend a stable array like

private static final @Stable AccessMode[] VALUES = values();

and users call this accessor instead.

The code in getMethodHandleUncached can benefit from this caching mechanism.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good suggestion.

@@ -90,7 +90,9 @@ public VarHandle withInvokeBehavior() {
@Override
@ForceInline
boolean checkAccessModeThenIsDirect(VarHandle.AccessDescriptor ad) {
super.checkAccessModeThenIsDirect(ad);
if (exact && accessModeType(ad.type) != ad.symbolicMethodTypeExact) {
Copy link
Member

Choose a reason for hiding this comment

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

Can we add a comment that the detailed UOE is thrown via directTarget.getMethodHandleUncached?

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually VarHandle::checkAccessModeThenIsDirect can call isAccessModeSupported so that this will check properly for IndirectVarHandle.

Copy link
Member

@JornVernee JornVernee left a comment

Choose a reason for hiding this comment

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

change VarHandle::checkAccessModeThenIsDirect to check if the access mode is unsupported. This check is only needed for direct var handle.

Note that IndirectVarHandle calls super.checkAccessModeThenIsDirect, so it ends up doing the check any way, I think?

Comment on lines 34 to 36
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Copy link
Member

@JornVernee JornVernee Jul 19, 2023

Choose a reason for hiding this comment

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

These two new imports seem unused.

@liach
Copy link
Member

liach commented Jul 19, 2023

Note that IndirectVarHandle calls super.checkAccessModeThenIsDirect, so it ends up doing the check any way, I think?

In the initial patch, it was distinct; it was migrated to call isAccessModeSupported in a subsequent change, so the change in IndirectVarHandle was rolled back and the VHs share a more consistent behavior.

@liach
Copy link
Member

liach commented Jul 19, 2023

Just curious, why does Paul Sandoz recommend removing the VarHandle itself from the UOE message?

@mlchung
Copy link
Member Author

mlchung commented Jul 19, 2023

I got feedback from @PaulSandoz. The patch is updated to include only the access mode information.

checkAccessModeThenIsDirect is on a performance sensitive path. We only need to modify VarForm::getMemberName to print out the access mode. Also mark getMemberName as @Hidden which then shows the call site from the top of the stack trace. The user can find out which VarHandle from the callsite from the stack trace location.

Copy link
Member

@liach liach left a comment

Choose a reason for hiding this comment

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

The enum values caching can be applied to AccessType as well; can be done in a separate patch, and I've created ticket at https://bugs.openjdk.org/browse/JDK-8312423.

@liach
Copy link
Member

liach commented Jul 20, 2023

Also just noticed copyright year of VarForm is still 2019; should be updated to 2023 with this patch.

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
Copy link
Member

Choose a reason for hiding this comment

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

I think you've updated the wrong copyright header?

@openjdk
Copy link

openjdk bot commented Jul 20, 2023

@mlchung This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

8199149: Improve the exception message thrown by VarHandle of unsupported operation

Reviewed-by: liach, jvernee

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 43 new commits pushed to the master branch:

  • 354c660: 8307185: pkcs11 native libraries make JNI calls into java code while holding GC lock
  • bae2247: 8308591: JLine as the default Console provider
  • b772e67: 8312395: Improve assertions in growableArray
  • 9fa944e: 8312019: Simplify and modernize java.util.BitSet.equals
  • fe41910: 8312459: Problem list java/awt/GraphicsDevice/DisplayModes/CycleDMImage.java for macOS
  • 8d29329: 8312320: Remove javax/rmi/ssl/SSLSocketParametersTest.sh from ProblemList
  • 94eb44b: 8312394: [linux] SIGSEGV if kernel was built without hugepage support
  • 3283328: 8311130: AArch64: Sync SVE related CPU features with VM options
  • a742767: 8312246: NPE when HSDB visits bad oop
  • 37c756a: 8305506: Add support for fractional values of SafepointTimeoutDelay
  • ... and 33 more: https://git.openjdk.org/jdk/compare/af5bf81754072fa5879726cfacb7404892b553f0...master

As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

➡️ To integrate this PR with the above commit message to the master branch, type /integrate in a new comment.

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Jul 20, 2023
Comment on lines +2007 to +2010
private static final @Stable AccessMode[] VALUES = values();
static AccessMode valueFromOrdinal(int mode) {
return VALUES[mode];
}
Copy link
Member

Choose a reason for hiding this comment

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

Also, I'll throw this out there, though I'm not sure how big of an issue it is: this array creation might have an effect on startup. But, since it is only used on a slow path right before we throw an exception (at least, at the moment), calling values() every time inside the valueFromOrdinal method, and avoiding the array creation on startup, might be 'better'.

Copy link
Member

Choose a reason for hiding this comment

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

I think this is a worthy change: see https://github.com/openjdk/jdk/pull/14943/files#diff-556b309ea2df3f5bfe8229de944183ef19750ce4511d0328cd59af2ce2b61ae2R135
that VarHandle.AccessMode.values() is called every time a polymorphic VH call is linked.

If the startup cost from array allocation is really problematic, we can make it stable and allocate VALUES on demand (at valueFromOrdinal calls).

Copy link
Member

Choose a reason for hiding this comment

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

Ah, so it looks like we are creating this array already, in adding the valueFromOrdinal method allows sharing. That sounds good!

Copy link
Member Author

Choose a reason for hiding this comment

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

The overhead is just one time allocation of an array of length 31, which is a very small array which I don't think such small array creation impacts as much.

I should have replaced other uses of AccessMode.values(). I will include that change in this patch.

@liach I don't know about AccessType.values() which seems to me not worth the change to add valueFromOrdinal as only calls that 6 times.

@mlchung
Copy link
Member Author

mlchung commented Jul 20, 2023

/integrate

@openjdk
Copy link

openjdk bot commented Jul 20, 2023

Going to push as commit d7b9416.
Since your change was applied there have been 43 commits pushed to the master branch:

  • 354c660: 8307185: pkcs11 native libraries make JNI calls into java code while holding GC lock
  • bae2247: 8308591: JLine as the default Console provider
  • b772e67: 8312395: Improve assertions in growableArray
  • 9fa944e: 8312019: Simplify and modernize java.util.BitSet.equals
  • fe41910: 8312459: Problem list java/awt/GraphicsDevice/DisplayModes/CycleDMImage.java for macOS
  • 8d29329: 8312320: Remove javax/rmi/ssl/SSLSocketParametersTest.sh from ProblemList
  • 94eb44b: 8312394: [linux] SIGSEGV if kernel was built without hugepage support
  • 3283328: 8311130: AArch64: Sync SVE related CPU features with VM options
  • a742767: 8312246: NPE when HSDB visits bad oop
  • 37c756a: 8305506: Add support for fractional values of SafepointTimeoutDelay
  • ... and 33 more: https://git.openjdk.org/jdk/compare/af5bf81754072fa5879726cfacb7404892b553f0...master

Your commit was automatically rebased without conflicts.

@openjdk openjdk bot added the integrated Pull request has been integrated label Jul 20, 2023
@openjdk openjdk bot closed this Jul 20, 2023
@openjdk openjdk bot removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Jul 20, 2023
@openjdk
Copy link

openjdk bot commented Jul 20, 2023

@mlchung Pushed as commit d7b9416.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

@mlchung mlchung deleted the JDK-8199149 branch August 2, 2023 20:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core-libs core-libs-dev@openjdk.org integrated Pull request has been integrated
Development

Successfully merging this pull request may close these issues.

3 participants