Skip to content

8299518: HotSpotVirtualMachine shared code across different platforms #11823

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 11 commits into from

Conversation

y1yang0
Copy link
Member

@y1yang0 y1yang0 commented Jan 3, 2023

harmless refactor to share code across different platforms of VirtualMachineImpl:

  1. Shared code to process command response after requesting a command execution
  2. Read functionality in SocketInputStream can be reused

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-8299518: HotSpotVirtualMachine shared code across different platforms

Reviewers

Reviewing

Using git

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

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

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 11823

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

Using diff file

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

@bridgekeeper
Copy link

bridgekeeper bot commented Jan 3, 2023

👋 Welcome back yyang! 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 Jan 3, 2023
@openjdk
Copy link

openjdk bot commented Jan 3, 2023

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

  • serviceability

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 serviceability serviceability-dev@openjdk.org label Jan 3, 2023
@mlbridge
Copy link

mlbridge bot commented Jan 3, 2023

@dholmes-ora
Copy link
Member

There are a lot of stylistic changes here that have nothing to do with refactoring or code sharing and they make the real changes very hard to see. At a minimum things like variable renaming should be done in a separate commit, so the refactoring is more obvious, but it may be better to use a separate cleanup RFE.

}
} catch (NumberFormatException x) {
throw new AttachNotSupportedException("Invalid process identifier: " + vmid);
int pid = Integer.parseInt(vmid);
Copy link
Member

Choose a reason for hiding this comment

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

This will now throw NumberFormatException instead of the expected AttachNotSupportedException.

Copy link
Member Author

@y1yang0 y1yang0 Jan 4, 2023

Choose a reason for hiding this comment

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

The same check is performed in its superclass HotSpotVirtualMachine. So we can be sure that it will not throw NumberFormatException and AttachNotSupportedException here

int pid;
try {
pid = Integer.parseInt(id);
} catch (NumberFormatException e) {
throw new AttachNotSupportedException("Invalid process identifier");
}

Copy link
Member

Choose a reason for hiding this comment

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

In that case the int pid determined by the superclass should be made available to the subclasses so they can use it and not need to re-parse the vmid.

Copy link
Member Author

Choose a reason for hiding this comment

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

In that case the int pid determined by the superclass should be made available to the subclasses so they can use it and not need to re-parse the vmid.

Hi @dholmes-ora, this is feasible, but in fact, the super class of VirtualMachine has already saved an unresolved pid(String) and corresponding getter method, so if we want to avoid re-parsing pid, we should save this parsed result in the parent class of the parent class of VirtualMachineImpl, and then modify the corresponding method, which seems to be beyond the scope of simple refactoring, so I hope avoiding re-parsing can be done by another PR

Copy link
Member

Choose a reason for hiding this comment

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

It is well within scope of improving code sharing in this arera, but I'm okay with leaving that for a next step.

@y1yang0 y1yang0 force-pushed the jdk_virtualmachienimpl branch from 293cccd to cb70000 Compare January 4, 2023 09:16
@openjdk
Copy link

openjdk bot commented Jan 4, 2023

@y1yang0 Please do not rebase or force-push to an active PR as it invalidates existing review comments. Note for future reference, the bots always squash all changes into a single commit automatically as part of the integration. See OpenJDK Developers’ Guide for more information.


public SocketInputStream(int s) {
this.s = s;
private static class SocketInputStreamImpl extends SocketInputStream {
Copy link
Member

Choose a reason for hiding this comment

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

Can this class definition also be shared by making it a protected nested class in the superclass?

Copy link
Member

Choose a reason for hiding this comment

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

Sorry I see it already is, but I think we can do better.

Copy link
Member Author

Choose a reason for hiding this comment

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

This(SocketInputStreamImpl) is implementation-specific, it calls platform-dependent VirtualMachine.xxx.

@@ -183,6 +184,8 @@ public void loadAgent(String agent, String options)
private static final int ATTACH_ERROR_NOTONCP = 101;
private static final int ATTACH_ERROR_STARTFAIL = 102;

// known error
private static final int ATTACH_ERROR_BADVERSION = 101;
Copy link
Member

Choose a reason for hiding this comment

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

It doesn't look right that this has the same value as ATTACH_ERROR_NOTONCP

Copy link
Member Author

Choose a reason for hiding this comment

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

They are located in different error families. The former is to deal with agent_load and the latter is to deal with command execution version errors.

@@ -366,6 +369,87 @@ String readErrorMessage(InputStream in) throws IOException {
return message.toString();
}

void processCompletionStatus(IOException ioe, String cmd, InputStream sis) throws AgentLoadException, IOException {
Copy link
Member

Choose a reason for hiding this comment

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

Some doc comments for this method would be good.

Copy link
Member

Choose a reason for hiding this comment

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

I was thinking more about describing what the parameters are - in particular it is unclear why the actual IOE can be replaced by a passed in one. If we wanted a custom message then I would at least expect to chain the actual IOE to the replacement.

Copy link
Member Author

Choose a reason for hiding this comment

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

I was thinking more about describing what the parameters are - in particular it is unclear why the actual IOE can be replaced by a passed in one. If we wanted a custom message then I would at least expect to chain the actual IOE to the replacement.

Done. Parameter ioe means if we get IOE during previous command execution, delay throwing it until command execution completion status has been read. Since all other parameters are straightforward and this is a private method, I don't write strandard @param descriptions for them.

Comment on lines 424 to 425
protected abstract int readImpl(long fd, byte[] bs, int off, int len) throws IOException;
protected abstract void closeImpl(long fd) throws IOException;
Copy link
Member

Choose a reason for hiding this comment

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

If the subclasses all override these in exactly the same way then these do not need to be abstract and can simply delegate to VirtualMachineImpl.xxx

Copy link
Member Author

Choose a reason for hiding this comment

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

All Posix OS platforms call the same VirtualMachineImpl.read/write/etc, but Windows is an unusual guy, it calls VirtualMachineImpl.readPipe/writePipe/etc

Copy link
Member

Choose a reason for hiding this comment

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

That is a shame, though perhaps we could just rename those methods on Windows?

This also raises the obvious question can we in fact reduce this to just a Windows and Posix version, or are there other differences between Linux, macOS etc that have to be accounted for? Though in that case we could introduce a shared superclass for the Posix platforms. Next steps perhaps?

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 remaining code for the POSIX system is exactly the same, except that Linux will make an extra attempt to find java_pid in cgroup environment.

@sspitsyn
Copy link
Contributor

sspitsyn commented Jan 5, 2023

I like the approach in general.
Also, I agree with David on his comments, especially on the renaming.
The abstract methods readImpl() and closeImpl() is better to name as read() and close().

Comment on lines 129 to 130
protected int read(long fd, byte[] bs, int off, int len) throws IOException {
return VirtualMachineImpl.readPipe(fd, bs, off, len);
Copy link
Member

Choose a reason for hiding this comment

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

If you add read/close methods for Windows that then call readPipe/closePipe, then we don't need to subclass and override.

Copy link
Contributor

@sspitsyn sspitsyn Jan 5, 2023

Choose a reason for hiding this comment

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

Good suggestion.
However, I wonder why the fd is casted from long to int on Unix. The Unix versions of SocketInputStream had int fd.
So, the following code also needs to cast fd to int:

+        public synchronized int read(byte[] bs, int off, int len) throws IOException {
+            if ((off < 0) || (off > bs.length) || (len < 0) ||
+                ((off + len) > bs.length) || ((off + len) < 0)) {
+                throw new IndexOutOfBoundsException();
+            } else if (len == 0) {
+                return 0;
+            }
+            return read(fd, bs, off, len);       <== ???
+        }
+
+        public synchronized void close() throws IOException {
+            if (fd != -1) {
+                close(fd);                  <== ???
+            }

Copy link
Member

Choose a reason for hiding this comment

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

Looks like Windows needs a long fd so the shared API takes long and we then cast to int for the Unix native methods. A little messy but fixable.

Copy link
Member Author

Choose a reason for hiding this comment

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

If you add read/close methods for Windows that then call readPipe/closePipe, then we don't need to subclass and override.

Sorry, I don't understand what this means. VirtualMachineImpl is platform-dependent while HotSpotVirtualMachine is shared, we always need to sub-class socket input stream in order to call platform-depend read/close.

Copy link
Member

Choose a reason for hiding this comment

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

As long as all the platform-specific VirtualMachineImpl classes define a read and close method then we can simply have the shared socket stream class call those methods. Windows will need an extra level of indirection because its read method will have to call readPipe.

Copy link
Member Author

@y1yang0 y1yang0 Jan 6, 2023

Choose a reason for hiding this comment

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

As long as all the platform-specific VirtualMachineImpl classes define a read and close method then we can simply have the shared socket stream class call those methods. Windows will need an extra level of indirection because its read method will have to call readPipe.

/path/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java:444: error: incompatible types: possible lossy conversion from long to int
            return VirtualMachineImpl.read(fd, bs, off, len);
                                           ^
/path/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java:449: error: incompatible types: possible lossy conversion from long to int
                VirtualMachineImpl.close(fd);

Unfortunately, this causes compilation error because we have long fd in shard socket stream and read(int fd...)/readPipe(long fd) in VirtualMachineImpl, we need subclasses to determine whether a type cast is necessary

Copy link
Member

Choose a reason for hiding this comment

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

That is unfortunate.

@plummercj
Copy link
Contributor

I would also like to request that the variable renames be omitted from this PR. They create too much noise and would best left to a PR that focuses on just the renames and possibly other style changes.

@y1yang0
Copy link
Member Author

y1yang0 commented Jan 9, 2023

I would also like to request that the variable renames be omitted from this PR. They create too much noise and would best left to a PR that focuses on just the renames and possibly other style changes.

Okay, reverted.

…chine.java

Co-authored-by: Andrey Turbanov <turbanoff@gmail.com>
Comment on lines 60 to 61
if (pid < 1) {
throw new AttachNotSupportedException("Invalid process identifier -1");
Copy link
Contributor

Choose a reason for hiding this comment

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

Why the change to using -1 instead of vmid? It seems presumptuous that it is -1, and also seems less useful than printing vmid.

@openjdk
Copy link

openjdk bot commented Jan 10, 2023

⚠️ @y1yang0 This pull request contains merges that bring in commits not present in the target repository. Since this is not a "merge style" pull request, these changes will be squashed when this pull request in integrated. If this is your intention, then please ignore this message. If you want to preserve the commit structure, you must change the title of this pull request to Merge <project>:<branch> where <project> is the name of another project in the OpenJDK organization (for example Merge jdk:master).

Comment on lines 453 to 455
if (fd != -1) {
close(fd);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

There used to be logic to set fd (previously called s) to -1 during the close operation. Is that no longer needed?

Copy link
Member Author

@y1yang0 y1yang0 Feb 15, 2023

Choose a reason for hiding this comment

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

Hi @plummercj , sorry for late reply.

I don't see why we need it because this method is protected by synchronized. fd is only set by ctor.

Copy link
Contributor

Choose a reason for hiding this comment

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

You will end up leaving fd set even after the close completes. A subsequent close (which I assume should never happen) would end up with an IOException. Previously close would end up not doing anything when called again, and simply return with no error. I'm not sure which is the best behavior in this case, but it is a change in behavior.

@bridgekeeper
Copy link

bridgekeeper bot commented Feb 9, 2023

@y1yang0 This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration!

@openjdk
Copy link

openjdk bot commented Feb 28, 2023

@y1yang0 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:

8299518: HotSpotVirtualMachine shared code across different platforms

Reviewed-by: cjplummer, dholmes

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 1283 new commits pushed to the master branch:

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 Feb 28, 2023
@y1yang0 y1yang0 requested review from dholmes-ora and sspitsyn and removed request for dholmes-ora March 3, 2023 02:07
@y1yang0
Copy link
Member Author

y1yang0 commented Mar 3, 2023

@sspitsyn @dholmes-ora @turbanoff May I ask your help to review this patch? Thanks.

Copy link
Member

@dholmes-ora dholmes-ora left a comment

Choose a reason for hiding this comment

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

Nothing further from me.

Thanks.

@y1yang0
Copy link
Member Author

y1yang0 commented Mar 6, 2023

/integrate

@openjdk
Copy link

openjdk bot commented Mar 6, 2023

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

  • 148900c: 8303562: Remove obsolete comments in os::pd_attempt_reserve_memory_at
  • 1bb39a9: 8302027: Port fdlibm trig functions (sin, cos, tan) to Java
  • 9fdbf3c: 8303588: [JVMCI] make JVMCI source directories conform with standard layout
  • 629a905: 8303242: ThreadMXBean issues with virtual threads
  • 5b2e2e4: 8302590: Add String.indexOf(int ch, int fromIndex, int toIndex)
  • cd4b88d: 8292269: Replace FileMapInfo::fail_continue() with Unified Logging
  • ae29054: 8303175: (fs) Deprecate com.sun.nio.file.SensitivityWatchEventModifier for removal
  • a04b104: 8303413: (fs) Ignore polling interval sensitivity modifiers in PollingWatchService
  • 9944314: 8303587: Remove VMOutOfMemoryError001 test from the problem list after 8303198
  • a50dc67: 8303527: update for deprecated sprintf for jdk.hotspot.agent
  • ... and 1299 more: https://git.openjdk.org/jdk/compare/11ba7591dfd3f7ca58e2e1ac6d1b3e81391f5bfb...master

Your commit was automatically rebased without conflicts.

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

openjdk bot commented Mar 6, 2023

@y1yang0 Pushed as commit 10d6a8e.

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
integrated Pull request has been integrated serviceability serviceability-dev@openjdk.org
Development

Successfully merging this pull request may close these issues.

5 participants