-
Notifications
You must be signed in to change notification settings - Fork 5.8k
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
Conversation
👋 Welcome back yyang! A progress list of the required criteria for merging this PR into |
Webrevs
|
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); |
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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
jdk/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java
Lines 69 to 74 in 38cfc59
int pid; | |
try { | |
pid = Integer.parseInt(id); | |
} catch (NumberFormatException e) { | |
throw new AttachNotSupportedException("Invalid process identifier"); | |
} |
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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 thevmid
.
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
There was a problem hiding this comment.
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.
293cccd
to
cb70000
Compare
@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 { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
protected abstract int readImpl(long fd, byte[] bs, int off, int len) throws IOException; | ||
protected abstract void closeImpl(long fd) throws IOException; |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
I like the approach in general. |
protected int read(long fd, byte[] bs, int off, int len) throws IOException { | ||
return VirtualMachineImpl.readPipe(fd, bs, off, len); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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); <== ???
+ }
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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 aread
andclose
method then we can simply have the shared socket stream class call those methods. Windows will need an extra level of indirection because itsread
method will have to callreadPipe
.
/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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is unfortunate.
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. |
This reverts commit cb70000.
Okay, reverted. |
src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java
Outdated
Show resolved
Hide resolved
…chine.java Co-authored-by: Andrey Turbanov <turbanoff@gmail.com>
if (pid < 1) { | ||
throw new AttachNotSupportedException("Invalid process identifier -1"); |
There was a problem hiding this comment.
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
.
…jdk_virtualmachienimpl
|
if (fd != -1) { | ||
close(fd); | ||
} |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
@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! |
@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:
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
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 |
@sspitsyn @dholmes-ora @turbanoff May I ask your help to review this patch? Thanks. |
There was a problem hiding this 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.
src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java
Outdated
Show resolved
Hide resolved
/integrate |
Going to push as commit 10d6a8e.
Your commit was automatically rebased without conflicts. |
harmless refactor to share code across different platforms of VirtualMachineImpl:
Progress
Issue
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