I need to limit the CPU and bandwidth of my application for testing purposes during the development process and wrote a small bash script wrapper around the java command, but I'm not sure how I can integrate this approach with IDEA's run/debug configuration.
#!/bin/bash
if [ $# -eq 0 ]
then
echo "Usage: javalimit [CPU Percentage] [download in kbps] [upload in kbps] [normal java args]"
echo "Required packages: trickle, cpulimit"
fi
CPU_PERCENTAGE=$1
DOWNLOAD_KBPS=$2
UPLOAD_KBPS=$3
shift 3
trickle -s -d $DOWNLOAD_KBPS -u $UPLOAD_KBPS java $#
TRICKLED_PID=$!
cpulimit --limit=$CPU_PERCENTAGE --pid=$TRICKLED_PID
My first failed approach for IDEA integration was
Statically set the cpu/down/up, removed shift
Copied my java folder to a new one, renamed java command, symbolic linked my script to bin/java
Told IDEA to use this JRE config - Crashed
Any insights on a better way to approach this problem would be appreciated!
I guess the best solution would be to use the Remote Debug as I've suggested in the similar question.
Related
I generated a JHipster app with Angular and Java, inside of a repository that I had previously made. I then generated some JDL classes with it and the build was successful, but when I tried to commit my changes in GitHub, it threw the following error:
Commit failed - exit code 1 received, with output: '.git/hooks/pre-commit: line 32: node: command not found'
I looked inside of my pre-commit file:
#!/bin/sh
# husky
# Hook created by Husky
# Version: 1.3.1
# At: 2/13/2019, 12:10:11 PM
# See: https://github.com/typicode/husky#readme
# From npm package
# Name: husky
# Directory: undefined
# Homepage: https://github.com/typicode/husky#readme
scriptPath="JHipsterProject/node_modules/husky/run.js"
hookName=`basename "$0"`
gitParams="$*"
debug() {
[ "${HUSKY_DEBUG}" = "true" ] && echo "husky:debug $1"
}
debug "$hookName hook started..."
if [ -f "$scriptPath" ]; then
# if [ -t 1 ]; then
# exec < /dev/tty
# fi
if [ -f ~/.huskyrc ]; then
debug "source ~/.huskyrc"
source ~/.huskyrc
fi
node "$scriptPath" $hookName "$gitParams"
else
echo "Can't find Husky, skipping $hookName hook"
echo "You can reinstall it using 'npm install husky --save-dev' or delete this hook"
fi
The error was in line 32:
node "$scriptPath" $hookName "$gitParams"
I'm not familiar with pre-commit files or how they work, but I currently have v10.15.0for Node.js, and 1.8.0_201 for my Java JDK and JRE. The version of JHipster I'm using is 5.8.1.
Is there anything I should change in this file, including line 32 in order to get rid of the error in my commit?
I'm also using the Visual Studio Code IDE if that helps at all.
Thanks in advance.
As #Stephen Savitzky suggested, it might be Node installation problem. However, if you're able to
Run application normally without an issue, and also
See no issues when doing git commits from terminal
Then, it's probably Node sourcing problem since the paths to it might be different from terminals or from GUI apps like VSC.
Your setup seems to be using husky for pre-commit hooks, so to ensure you have the right Node version, you could add ~/.huskyrc as suggested in the docs:
# ~/.huskyrc
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
Then, you can source Node from NVM (if you use one) or another source. It's also a good way to debug what's actually going on when husky hook scripts kick in.
"node: command not found" means that there is no program called node on any of the directories in $PATH, the environment variable that tells the shell where to look for programs. Hooks are usually run with a very restricted $PATH; e.g. /bin:/usr/bin.
The best way to deal with this is to use an absolute path for any programs that aren't installed in either /bin or /usr/bin. You can find out what path to use with the which command:
> which node
/home/steve/.nvm/versions/node/v10.6.0/bin/node
Of course, it's also possible that node isn't installed at all on the machine the hook is running on.
You can add new entry to the Windows PATH environment variable using the Command Prompt as follows:
SET PATH=C:\Program Files\Nodejs;%PATH%
npm
Or you can set the PATH variable by using Windows graphical UI. (Annoying for me :/ )
For me, I use bash as default shell and my ~/.bashrc has got a whole bunch of paths set, whereas my .git/hooks/pre-commit was as follows:
#!/bin/sh
exec mvn spotless:check
Changed #!/bin/sh -> #!/bin/bash and ta-da! all works
if you are using nvm there is the fix
#!/bin/bash
. $HOME/.nvm/nvm.sh
./node_modules/pre-commit/hook
RESULT=$?
[ $RESULT -ne 0 ] && exit 1
exit 0
Ref: https://github.com/observing/pre-commit/issues/139#issuecomment-437138661
I'm trying to build AOSP from source (With a few modifications) but my build stops with
[ 0% 1/35196] JarJar: out/target/common/obj/JAVA_LIBRARIES/conscrypt_intermediates/classes-jarjar.jar
FAILED: /bin/bash -c "java -jar out/host/linux-x86/framework/jarjar.jar process external/conscrypt/jarjar-rules.txt out/target/common/obj/JAVA_LIBRARIES/conscrypt_intermediates/classes-full-debug.jar out/target/common/obj/JAVA_LIBRARIES/conscrypt_intermediates/classes-jarjar.jar"
Error: Could not find or load main class com.tonicsystems.jarjar.Main
ninja: build stopped: subcommand failed.
make: *** [build/core/ninja.mk:149: ninja_wrapper] Error 1
and i can't get to fix it. My source is hosted here and the path of external/jarjar is the stock one on googlesource.
Can anyone help?
I had the same problem until I realized that it's due to the wrong path where com.tonicsystems.jarjar.Main is located. At ~/android/system, JarJar's com.tonicsystems.jarjar class is located in:
external/jarjar/src/main/com/tonicsystems
When it should be
external/jarjar/src/main/java/com/tonicsystems
Like it's source (from GitHub)
src/main/java/com/tonicsystems/jarjar
P.S: I had to create the external/jarjar/src/main/java directory and then move the source.
I've run into this with an AOSP fork (I think Qualcomm's tree) before - that was caused by the Makefile fragments that generate the file lists for the jar files not dealing properly with localized versions of the "sort" utility (causing removal of important class files in addition to the duplicates that were supposed to be removed).
I don't remember all the details or the proper fix, but the workaround that got me going initially was simply disabling localization while building.
rm -rf out
export LANG=C
export LC_ALL=C
export LC_COLLATE=C
. build/envsetup.sh
lunch whatever
make droidcore -j8
What fixed this for me was something completely unrelated to jarjar itself.
I was building AOSP 7.1.1 on Ubuntu 20.04. The default python command on Ubuntu 20.04 points to python3 [1], but AOSP 7.1.1 builds using python (which is really python 2.7.5).
I updated my system with sudo apt install python which linked the python command to python2 correctly instead of python3. After this, I built successfully.
AOSP is shipped with python under the prebuilts/python directory and I'm still confused as to why the build system doesn't point to that python version.
Edit
I had more trouble with adjusting my system to use the correct version of python, ultimately I had to add python and python3 as alternatives.
$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python2 1
$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 2
$ sudo update-alternatives --config python
Select python2
I have written a Java application that analyzes my phone bills and calculates the average. At the moment I execute it like:
$ java -jar analyze.jar bill_1.pdf bill_2.pdf
But I want to install the application to my system. So I can just fire up a terminal type in the name of the application and the arguments and hit enter. Like any other "normal" program.
$ analyze bill_1.pdf bill_2.pdf bill_3.pdf
I know I can write a shell script and install it to "/usr/bin/" but I can't believe that there is no "native" way.
So please help, sorry for dump question.
Thank's in advance
One neat little trick is that you can append a basic shell script to the start of the jar file which will run it appropriately. See here for the full example but the basics are:
stub.sh
#!/bin/sh
MYSELF=`which "$0" 2>/dev/null`
[ $? -gt 0 -a -f "$0" ] && MYSELF="./$0"
java=java
if test -n "$JAVA_HOME"; then
java="$JAVA_HOME/bin/java"
fi
exec "$java" $java_args -jar $MYSELF "$#"
exit 1
Then do...
cat stub.sh helloworld.jar > hello.run && chmod +x helloworld.run
And you should be all set! Now you can just call the script-ified jar directly.
./helloworld.run
What you did so far is basically "the native" way.
You have to keep in mind: Java applications are compiled to byte code. There simply is no binary for your application that you could invoke. You do need this detour of calling some JVM installation with a pointer to the main class you want to run. In owhther words; that is what the vast majority of java applications are doing.
Theoretically, there are products out that there that you could use to actually create a "true" binary from your application; but that isn't an easy path (see here for first starters); and given your statement that your just looking for more "convenience" it is definitely inappropriate here.
I'm writing an application that leverages jsvc to start up a Java service as a daemon. I need to use something like jsvc because my application utilizes ports under 1024 and yet I'd really like to not run it as root so that created files are owned by another user. I'd also like to keep dependencies and configuration to a minimum so that all the client needs is a JVM and the jsvc binary installed.
However, it seems that jsvc has one major catch; it can't detect the home folder of Java on a given Unix operating system, which is quite frustrating:
$ ./startup.sh
Cannot locate Java home
I have been able to work around the issue on Ubuntu at least by manually setting the JVM home directory:
jsvc ... -home /usr/lib/jvm/default-java/ ...
Is there any way to determine the Java home directory dynamically from a Bash script so I can make this work across most Unixes/Linuxes? I'd be able to sleep much better at night doing something like:
JAVA_HOME="$( ... )"
jsvc ... -home "$JAVA_HOME" ...
...rather than hard-coding for each individual operating system. Is there a way that, given a java binary, I can find the home directory of its JVM/JRE?
Not sure if this works across *nixes, but found this solution:
JAVA_HOME="$( readlink -f "$( which java )" | sed "s:bin/.*$::" )"
I've tested it on Ubuntu and it works, however it does not work for OSX.
My solution was compiling the native linux source as the main jsvc page says in
http://commons.apache.org/proper/commons-daemon//jsvc.html
Here is my step by step procedure
Download www.fightrice.com/mirrors/apache/commons/daemon/source/commons-daemon-1.0.13-src.tar.gz
Once you extract the file then go to ...../commons-daemon-1.0.13-src/src/native/unix
in terminal as a root do the following:
$ support/buildconf.sh
$ ./configure --with-java=/usr/lib/jvm/default-java
$ make
test generated jsvc binary app
$ ./jsvc -help
It works! cleanly.
Use dirname and which commands to find Java's bin directory:
echo `dirname \`which java\``
JAVA_HOME=`dirname \`which java\``
... Only works if Java is already on the $PATH.
One other way is :
type -p java
Expect this to return the correct JAVA installation folder.
I just want to be able to do ./whatever.jar instead of java -jar whatever.jar.
I've found a way:
#!/bin/bash
java -jar $0 $*
exit
# jar goes here...
but it doesn't work. Java just complains that it's an invalid/corrupt jarfile.
I also tried piping:
#!/bin/bash
tail -n +4 $0 | java -jar
exit
# jar goes here...
but this doesn't work.
One way to do it is to somehow split the file into two separate parts (the script part and the jar part), and then execute the jar, but that'd be redundant. You'd might as well make a script that executes the jar and execute that script.
So I need to figure out how to somehow tail it and fake the file.
I thought I could do it using /dev/stdout:
#!/bin/bash
java -jar /dev/stdout
tail -n +5 $0
exit
# jar goes here...
That doesn't work either. It just prints the contents of the jar and java complains that it's invalid. (I figured out later that there's nothing to read in /dev/stdout)
So I need to read from stdout some other way. I really wish I could pipe it though. It would make things SO much easier :)
You need a service called jexec some linux distros come with this installed check for /etc/init.d/jexec. My CentOS 5.5 definitely does.
What it does is register the jexec interpreter with the binfmt system.
For more information you might what to have a quick read of binfmt_misc.
Assuming you have the kernel source code installed, check out /usr/src/linux/Documentation/java.txt for a way to run Java code directly using the kernel's BINFMT_MISC support (assuming it's compiled into the version of the kernel you're running, but I think it is on most major distros). If you don't have the source installed, you should be able to find it online easy enough (here's one example).
FYI, if you wanted to do it your original way it would go like this:
$ cat jar.sh
#!/usr/bin/env bash
java -jar <(tail -n +4 "$0")
exit
$ cat jar.sh runme.jar > works.jar
$ chmod a+x works.jar
$ ./works.jar
Presuming a recent bash with support for <()
java -jar does not work with stdin, apparently it does some seeks rather than straight reads.
On a system you can't mod, you have to use a tmp. for example.
#!/bin/bash
JF=/tmp/junk$$.jar
(uudecode -o /dev/stdout >$JF;java -jar $JF;unlink $JF) <<JAR
begin-base64 644 junk.jar
UEsDBBQACAAIAEaBz0AAAAAAAAAAAAAAAAAJAAQATUVUQS1JTkYv/soAAAMA
UEsHCAAAAAACAAAAAAAAAFBLAwQUAAgACABGgc9AAAAAAAAAAAAAAAAAFAAA
AE1FVEEtSU5GL01BTklGRVNULk1G803My0xLLS7RDUstKs7Mz7NSMNQz4OVy
LkpNLElN0XWqBAmY6RnEG5koaASX5in4ZiYX5RdXFpek5hYreOYl62nycvkm
ZubpOuckFhdbKWSV5mXzcvFyAQBQSwcIBHn3CVkAAABZAAAAUEsDBBQACAAI
AEd+z0AAAAAAAAAAAAAAAAAKAAAAanVuay5jbGFzc21QTUvDQBB926RJE6Ot
ramfhXoQogcDXiteBPFQVIjowdOmXcrGZCMxEfxZelDw4A/wR4mzUShCF3Zn
9s2bt2/26/vjE8ARBi4stB10sNpC10UPazZ8G30G61gqWZ4wGMH+DYN5mk8F
Q3sslbioslgU1zxOCTEzLhVDP7gbJ/yJhylXszAqC6lmI93oRnlVTMSZ1GQn
qdT9oeZ5sNGyse5hA5sM3rlI03x4mxfpdNfGlodt7JC45jN05sqXcSIm5T8o
en4sRUZG84oK/q8NmYdX5KEkJ4JnI4beApjBftC3lAbwg0X+MUSTvkivBm3y
DJqCsgFFRrF58A72QglNSqdVg5qyBO+PuketGnVe0egabzDndLdWNUjVJGS5
fmXlB1BLBwjDUWL/IAEAAJ4BAABQSwECFAAUAAgACABGgc9AAAAAAAIAAAAA
AAAACQAEAAAAAAAAAAAAAAAAAAAATUVUQS1JTkYv/soAAFBLAQIUABQACAAI
AEaBz0AEefcJWQAAAFkAAAAUAAAAAAAAAAAAAAAAAD0AAABNRVRBLUlORi9N
QU5JRkVTVC5NRlBLAQIUABQACAAIAEd+z0DDUWL/IAEAAJ4BAAAKAAAAAAAA
AAAAAAAAANgAAABqdW5rLmNsYXNzUEsFBgAAAAADAAMAtQAAADACAAAAAA==
====
JAR
Or I could just install the jarwrapper (Ubuntu) package.
Write a separate shell script:
whatever.sh
#!/bin/bash
java -jar whatever.jar $*
You can't make the JAR file directly executable because it's not an executable file. It's Java bytecode which can't be read directly by the machine nor any standard shell interpreter that I know of.