KEMBAR78
Change jfrconv binary generation from cpp to shell. by roy-soumadipta · Pull Request #1366 · async-profiler/async-profiler · GitHub
Skip to content

Conversation

roy-soumadipta
Copy link
Contributor

@roy-soumadipta roy-soumadipta commented Jul 7, 2025

Description

The commit fixes #1344 and includes the following changes:

  • Rewrite jfrconv launcher script in shell from cpp.
  • Changes to Makefile to accomodate the shift to shell script.

Related issues

#1344

Motivation and context

How has this been tested?

jfrconv has been tested to show no Move to trash popup by using the binaries from the notarized zip.


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

The commit fixes async-profiler#1344 and includes the following changes:

* Rewrite jfrconv launcher script in shell from cpp.
* Changes to Makefile to accomodate the shift to shell script.
@roy-soumadipta roy-soumadipta marked this pull request as draft July 7, 2025 13:44
@roy-soumadipta roy-soumadipta marked this pull request as ready for review July 15, 2025 09:28

set -euo pipefail

VERSION_STRING="JFR converter PROFILER_VERSION built on $(date '+%b %d %Y')"
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 today's date, not the build date, right?

Copy link
Contributor Author

@roy-soumadipta roy-soumadipta Jul 15, 2025

Choose a reason for hiding this comment

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

Yes replaced at build time like a macro. Will reflect in next commit

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in commit 444fb5d

Comment on lines 15 to 19
if [[ "$OSTYPE" == "darwin"* ]]; then
SCRIPT_PATH="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")"
else
SCRIPT_PATH="$(readlink -f "$0")"
fi
Copy link
Member

Choose a reason for hiding this comment

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

Is canonicalization necessary? java -jar accepts relative paths too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is such a great suggestion. Thanks can be simplified so much

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in commit 444fb5d

SCRIPT_PATH="$(readlink -f "$0")"
fi

JAVA_CMD=("java" "-Xss2M" "-Dsun.misc.URLClassPath.disableJarChecking")
Copy link
Member

Choose a reason for hiding this comment

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

Why put java in the beginning, if it's always cut later?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes changed here and other affected places

# Copyright The async-profiler authors
# SPDX-License-Identifier: Apache-2.0

#!/bin/bash
Copy link
Member

Choose a reason for hiding this comment

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

bash is not available on all systems. Script must use POSIX compatible /bin/sh.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in commit 444fb5d

run_java() {
# 1. Try JAVA_HOME
if [[ -n "$JAVA_HOME" ]] && find_java "$JAVA_HOME/bin/java"; then
exec "$JAVA_HOME/bin/java" "${JAVA_CMD[@]:1}"
Copy link
Member

Choose a reason for hiding this comment

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

Script should continue trying next options if one of exec calls fails.
This is how the original C++ launcher worked.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in commit 444fb5d

exit 1
}

run_java No newline at end of file
Copy link
Member

Choose a reason for hiding this comment

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

Newline here is required not only because of the coding style, but also because it won't work otherwise after concatenation with .jar.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in commit 444fb5d


JAVA_CMD+=("-jar" "$SCRIPT_PATH" "$@")

find_java() {
Copy link
Member

Choose a reason for hiding this comment

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

Not very meaningful function - there is just one short expression that can be as well inlined.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in commit 444fb5d

Makefile Outdated

clean:
$(RM) -r build
$(RM) -r build
Copy link
Contributor

Choose a reason for hiding this comment

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

You have styling issue here & in other files
The file should always end with a single empty new line

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in latest commit


#!/bin/bash

set -euo pipefail
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need this on user script?
This might end up causing weird failures on user side if we're not careful

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Isn't this better than silent failures?

Copy link
Contributor

Choose a reason for hiding this comment

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

Some failures that happen due to set -euo pipefail are due to reasons that would work fine without the flags

Such as unbound variables

I'm fine with keeping this but we should test all possible branches of the script

If all possible branches were not tested then this isn't really safe

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Which ones do you suggest removing?

Copy link
Contributor

Choose a reason for hiding this comment

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

All of them raise some level of risk

The question shouldn't be "which to remove"

The proper question should be were all possible cases tested with these flags?

If we have enough testing then keeping this should be fine

For example the script should continue even if a previous exec fails right?

However if an exec fails wouldn't it cause an exit code of 1?

Wouldn't this break the script?

Copy link
Member

Choose a reason for hiding this comment

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

Let's not delve into philosophy. A simple answer is - leave options that are necessary and delete those that aren't.
To me, -e does not seem useful here: there are basically no commands that can fail except for exec, but I explicitly noted that the script should proceed if exec fails.
The same for pipefail: I don't see why it is here, given there are no pipes in the script.
While -u is generally useful, again, it has no behavior impact in this particular script.
Please correct me if I'm wrong, otherwise just remove the entire line. The less code, the better.

fi

if [[ "$OSTYPE" == "darwin"* ]]; then
SCRIPT_PATH="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")"
Copy link
Contributor

Choose a reason for hiding this comment

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

pwd)?

wouldn't realpath $0 solve for both?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is removed after Andrei's suggestion

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in commit 444fb5d

fi

# 2. Try PATH
if command -v java >/dev/null 2>&1; then
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we really need all this logic for finding java
can't we use PATH always?

if missing we can print a message telling the user to add it?
If the problem is with our jar being compatible with a specific minimum Java version, we can add a check for that as well

This logic might be hiding bugs as if the user has 10 JDKs it could be failing for the first 9 while passing for the last one

@apangin what do you think?

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 the script is doing what it's intended to do - find any working Java Runtime, even if java is not on the PATH.

exit 0
fi

if [[ "$OSTYPE" == "darwin"* ]]; then
Copy link
Contributor

Choose a reason for hiding this comment

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

why not use uname -s as we do in Makefile?

Copy link
Contributor Author

@roy-soumadipta roy-soumadipta Jul 16, 2025

Choose a reason for hiding this comment

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

We have an env variable ready to use. Why go through uname -s?

Copy link
Contributor

Choose a reason for hiding this comment

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

For consistency

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't get how are we deviating from consistency by using a ready to use variable?

Copy link
Contributor

Choose a reason for hiding this comment

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

Different approach than what we have in the Makefile

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in aeb211f to maintain uniformity and posix compliance

run_java() {
# 1. Try JAVA_HOME
if [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then
"$JAVA_HOME/bin/java" "${JAVA_CMD[@]}" && exit 0
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not exec?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For fallback as per Andrei's comment on the previous commit. With prev commit when exec command itself failed it would proceed to try the next for example if java is not present in the path corresponding to the exec command. But now if the exec succeeds but then encounters an error, it won't try the subsequent alternatives. @apangin is this the change you wanted or the previous impl using exec suffices your expectation?

Copy link
Contributor Author

@roy-soumadipta roy-soumadipta Jul 16, 2025

Choose a reason for hiding this comment

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

@apangin I checked again and in the previous launcher cpp, there was no fallback if exec succeeds but then error encountered. So the previous impl in shell script sufficed the need as per the existing one. Should I revert again or do you want the changes now for a better fallback?

Copy link
Member

Choose a reason for hiding this comment

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

Script should proceed with the next attempt if exec itself fails, not the target command. There should be no fallback when java process is launched but fails for whatever reason. Basically, the script should retain the same behavior as in the original launcher.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok I will change it accordingly. The previous one however wouldn't have proceeded due to set -e. There is a comment from @Baraa-Hasheesh regarding the set -euo pipefail. @apangin if you can share your thoughts so that I can make this change accordingly

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 385001b

# Copyright The async-profiler authors
# SPDX-License-Identifier: Apache-2.0

#!/bin/sh
Copy link
Member

Choose a reason for hiding this comment

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

Shebang must stay on the first line. License header shall come after.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 385001b


#!/bin/bash

set -euo pipefail
Copy link
Member

Choose a reason for hiding this comment

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

Let's not delve into philosophy. A simple answer is - leave options that are necessary and delete those that aren't.
To me, -e does not seem useful here: there are basically no commands that can fail except for exec, but I explicitly noted that the script should proceed if exec fails.
The same for pipefail: I don't see why it is here, given there are no pipes in the script.
While -u is generally useful, again, it has no behavior impact in this particular script.
Please correct me if I'm wrong, otherwise just remove the entire line. The less code, the better.


set -euo pipefail

VERSION_STRING="JFR converter PROFILER_VERSION built on BUILD_DATE"
Copy link
Member

Choose a reason for hiding this comment

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

There is no much value in introducing variables that are used only once in a local context.
Just inline the string where needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 385001b

exit 0
fi

SCRIPT_PATH="$0"
Copy link
Member

Choose a reason for hiding this comment

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

Same as above.
Good code is like a poem: every word counts.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 385001b


JAVA_CMD+=("-jar" "$SCRIPT_PATH" "$@")

run_java() {
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason to put it in a function, if the following code is executed as is anyway?
E.g., the above argument parsing logic is not in a function, and that's fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since this is not a big script it can be removed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 385001b

test.html Outdated
Copy link
Member

Choose a reason for hiding this comment

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

Added by mistake

JAVA_CMD+=("-jar" "$0" "$@")

# 1. Try JAVA_HOME
if [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then
Copy link
Member

Choose a reason for hiding this comment

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

AFAIK, [[ is also a bash extension. Strictly POSIX-compliant shell only supports [.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Had to make other changes as well for full compliance. Addressed in 52af9cc

fi
;;
-agent*)
if [ "$(echo "$1" | cut -c1-6)" = "-agent" ]; then
Copy link
Member

Choose a reason for hiding this comment

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

What does this expression verify? Don't we get in this case only if the argument starts with -agent?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes this is redundant. Removed in 6f07677

roy-soumadipta and others added 2 commits July 17, 2025 15:12
Signed-off-by: Andrei Pangin <1749416+apangin@users.noreply.github.com>
@apangin apangin merged commit 5fffdb1 into async-profiler:master Jul 17, 2025
7 checks passed
@apangin
Copy link
Member

apangin commented Jul 17, 2025

Merged, thanks!

@roy-soumadipta roy-soumadipta deleted the issue_1344 branch July 17, 2025 17:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sign jfrconv executable on macOS

4 participants