Maven and JVM relation - java

Though not a direct programming question, it is related to Maven and JVM
While I was going thru this link - http://maven.apache.org/archives/maven-1.x/reference/command-line.html
Update of links: https://wiki.openstack.org/wiki/Documentation/Troubleshooting
https://maven.apache.org/docs/3.0/release-notes.html
it says about MAVEN_OPTS
"Specify additional options using the MAVEN_OPTS environment variable. It is for passing parameters to the Java VM when running Maven. For example, to increase the amount of memory to 1024 Meg for the entire run of Maven, use:
MAVEN_OPTS=-Xmx1024m "
Questions:
How Maven is able to set the JVM properties?
Why does Maven need JVM? It just build the war and JVM is needed only when u deploy the WAR to appserver.right?
Does Maven starts the JVM and stop it after use? IF it stops it after use, what's the point in setting more heap size?
My understanding after research:
(1) How/Why Maven is able to set the JVM properties?
Maven will be able to set the JVM properties using MAVEN_OPTS.
It is to pass the parameter to JVM for that run of Maven
(2) Why does Maven need JVM? Maven is just a build tool..
Maven has to build the WAR file, right? To build the WAR file, you need to compile the code,
and sometimes run the test cases. To compile the code, you need JVM. To run test cases you need JVM.
Don't know where else we need JVM when we do a mvn clean deploy.
[eg of javac passing JVM parameters otherwise: javac -d build/classes -classpath ... -J-Xms256m -J-Xmx1024m java-source-files]
(3) Does Maven starts the JVM and stop it after use? IF it stops it after use, what's the point in setting more heap size?
Yes , Maven starts the JVM and stop after its use. JVM is needed during its run. like if maven build needs lot of memory [like if you do XML processing] then
setting the heap memory using MAVEN_OPTS will be helpful.
Please clarify on my understanding especially on the second question

mvn is a shell script/batch file, and it uses MAVEN_OPTS to do what you'd expect.
Maven is Java. Maven tasks are written in Java.
...? Maven does a lot, and some of those things use memory. It's just a Java program. When it ends the JVM that was running it also ends.
To further clarify point 1, this is what happens at the end of the script:
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "${M2_HOME}"/boot/plexus-classworlds-*.jar \
"-Dclassworlds.conf=${M2_HOME}/bin/m2.conf" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${CLASSWORLDS_LAUNCHER} "$#"
Note: why read Maven 1 docs?

Maven is a program written in Java. This program is used to compile files, copy files, make jar files, and a whole lot of other tasks. As any Java program it needs a JVM to run. And as any Java program it uses memory. And as any Java program using memory, it can cause ot of memory errors if you don't start the JVM with enough memory.
mvn is able to set JVM properties because it's a simple shell script that starts a Java program: Maven.
And yes, once mvn exits, the JVM it started to run all the tasks it needs to run exits too.

Related

OpenJDK Needs More Memory in Gradle Project [duplicate]

I have an application. I run it via
gradlew run-app
Or debug
gradlew debug-app
It works. How do I pass '-Xmx' argument into the application which I run (debug)?
Is it possible to do so without edditing build.gradle file?
I found this
Gradle unknown command-line option '-X'
I get a similar error when I try
gradlew debug-app -Xmx2000m
Error
FAILURE: Build failed with an exception.
* What went wrong:
Problem configuring task :debug-app from command line.
> Unknown command-line option '-X'.
I tried to create a file gradle.properties in GRADLE_USER_HOME directory (by default, it is USER_HOME/.gradle).
org.gradle.jvmargs=-XX\:MaxHeapSize\=4256m -Xmx4256m -Xms2000m
I also tried to org.gradle.jvmargs=-Xmx2000m in project folder gradle.properties.
And even then when I run an application, I see Commited Memory size is < 520 MiB
And this is when I run it as a normal Java App
In the second case, when I run the application as a normal Java app with -Xms, -Xmx, Commited Memory size is about 3.5 GiB because I passed -Xmx4512m -Xms2512m parameters.
Add this in your gradle.properties file :
org.gradle.jvmargs=-Xmx2000m
From here
org.gradle.jvmargs
Specifies the jvmargs used for the daemon process. The setting is
particularly useful for tweaking memory settings. At the moment the
default settings are pretty generous with regards to memory.
edit : my answer what about the gradle daemon jvm, not the app jvm. You have to use the jvmArgs property
The extra arguments to use to launch the JVM for the process. Does not
include system properties and the minimum/maximum heap size.
Firstly, thanks #ToYonos for leading me to the right direction.
Secondly, I found the solution here https://stackoverflow.com/a/9648945/4587961.
I ran my app from command line.
set GRADLE_OPTS=-Xms1724m -Xmx5048m
gradlew debug-app
Note, CMD Windows command SET works locally, so if you close your terminal, GRADLE_OPTS will not be set. For Linux, you can use
export GRADLE_OPTS=WHATEVER
This is what I wanted to achieve.
Using application plugin one can use applicationDefaultJvmArgs property
apply plugin: 'application'
applicationDefaultJvmArgs = ["-Xms1024m", "-Xmx2048m"]
The arguments will be applied to run task and to start script of your application
more info
In my case Invalidate cache and restart the android studio(which is automatically restarted) then the error will be gone after restarting the android studio
then

Add specific JRE to .Net Dockerfile

I'm setting up a .net Docker image, with some .net code within it. The code, however, needs access to a very specific version of Java Runtime (jre-7u9-windowsx64.exe).
I don't know exactly where to start in adding this executable into my dotnet Dockerfile.
The current Dockerfile for dotnet
FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build-env
WORKDIR /name
# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore
# Copy everything else and build
COPY . ./
RUN dotnet publish -c Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "name.dll"]
I would just like to get the JRE added to the Dockerfile so it is installed or available when Docker spins up.
Because the JRE forms part of your runtime environment, you're going to want to install it into your # Build runtime image.
Your ideal goal is to find the lowest common multiple, sufficient to run both ASP.NET and your .NET code and the JRE and your Java code.
Option #1: Find a (trusted) container image that runs both ASP.NET and JRE
Presumably, you've pursued this approach and been unsuccessful.
Option #1: Start from your currently working solution and add
I'm unfamiliar with mcr.microsoft.com/dotnet/core/aspnet but this may well continue to suffice as your baseline and it has the advantage that you know it will run your .NET app.
So, your process will be to determine what additionally -- if anything -- you'll need to install to be able to run jre-7u9-windowsx64.exe.
A hacky way to determine this would be to insert whatever the installer is for this binary (between lines 13-14). This will take the form RUN the jre-7u9-windowsx64.exe installer. Then, try to build your container and see what errors arise.
A more considered approach would be to identify whether you need to install additional packages to support jre-7u9-windowx64.exe and, if you do, you'll need to install those (using further RUN ...) commands beforehand.
Option #2: Start from a minimal baseline and add
Alternatively, you could start from a more foundational baseline. I assume the OS here is Windows rather than Linux. Presumably there's a minimal Windows container image?
Then you'd need to add whatever is needed to:
Get ASP.NET and your .NET code working
Get JRE and your Java code working
This would provide a more considered foundation for your image but at the cost of requiring you to solve two puzzles.
Option #3: Start from a working JRE image and add
Included for completeness but not-recommended in this case.

Java 8 Memory allocation

Let's assume that I have JDK/JRE 8 also I've added JAVA_OPTS= -Xmx8G -Xms1G.
I've stated without any other params (java -jar 1.jar; java -jar 2.jar) 2 simple jars. So now I have two java process.
1) Do they executed in one JVM (as two java process) or each process will be executed in separated JVM?
2) -Xmx8G -Xms1G heap size will be applied to separately each of two executed jars or this heap size will be something common for two executed jars?
3) What will be with memory allocation if start one jar ( java -jar 1.jar)
and another with java -jar 2.jar Xmx12G?
P.S. Would we nice if you have any good links.
P.S.S Don't Ask what I'm smoking :)
The best way is to analyze JVM instances in your system. Just open JMC(Java Mission Control). Whenever you execute any application it will show as an individual jvm there. ex : if you run jar1 and jar2 the JMC will show three JVMs- jar1, jar2 ,jmc. Then, you can use use MBean Browser there to analyze your all jvm.
Hope it helps.

sbt won't assemble Spark

I am having issues assembling Spark using the sbt on my machine.
Attempting the assembly without allocating extra memory either runs out or times out on the garbage collector; the exact issue has been different at different times I have tried. However, any attempt to modify the allocated memory, either through Xmx or Xms, and whether giving more or restricting, fails as the sbt doesn't recognize -Xmx or -Xms as a command.
Here is a sample of the kind of command I have been trying (from the source directory of Spark):
sbt -Xmx2g assembly
Here is the error I have been receiving:
java.util.concurrent.ExecutionException:java.lang.OutOfMemoryError: GC overhead limit exceeded
Use 'last' for the full log.
Not a valid command: Xmx2g
Not a valid project: Xmx2g
Expected ':' (if selecting a configuration)
Not a valid key: Xmx2g
Xmx2g
^
I am running 64-bit Java, version 1.8.0_20.
Try creating a new environment variable SBT_OPTS, with the value "-XX:MaxPermSize=1024m". That should give sbt the memory it needs without producing your error.
Check the docs: Building Spark with Maven.
Setting up Maven’s Memory Usage
You’ll need to configure Maven to use more memory than usual by setting MAVEN_OPTS. We recommend the following settings:
export MAVEN_OPTS="-Xmx2g -XX:MaxPermSize=512M -XX:ReservedCodeCacheSize=512m"
Then you can build it with:
mvn -DskipTests package

Classpath limitation in Linux

We are executing standalone java program from shell script, having a comman script to mention classpath, path, etc..In this common script, we have added several classpaths now and number of character is more than 9000.
It is working fine in the test env. Will it cause any issue in Production? Any limitation is there in linux to set classpath? What is the max char for command line inputs...
No, there is no limitation. In Windows there is (8191 characters), but not under Linux. We work with the concept of classpath-files. These file lists all the dependencies for the application, eg:
...
libs/org/easymock/easymock/2.2/easymock-2.2.jar
libs/org/hamcrest/hamcrest-core/1.1/hamcrest-core-1.1.jar
libs/org/hibernate/hibernate-envers/4.1.0.Final/hibernate-envers-4.1.0.Final.jar
libs/com/google/inject/guice/3.0/guice-3.0.jar
...
and then we convert this into usable classpath and run the application as follows:
#!/bin/bash
CLASSPATH_FILE=`ls -r1 ${APP-HOME}/classpaths/myapp*.classpath | head -n1`
CLASSPATH=$(cat $CLASSPATH_FILE | sed 's_^libs_ ${APP-HOME}/libs_' | tr -d '\n' | tr -d '\r' | sed 's_.jar/libs/_.jar:/libs/_g' | sed 's_.pom/libs/_.pom:/libs/_g')
java -d64 -cp $CLASSPATH com.blah.main.Main $#
We have never run into problems and these classpath entries gets pretty huge.
EDIT: As a side note, you can use the maven dependency plugin to generate a list of dependencies.
See this stackoverflow answer about maximum linux command line lengths.
The maximum command line length will be roughly between 128KB and 2MB.
The max size of any one argument is considerably smaller, though, and 9000 chars might be problematic.
When you use in your Java program some classes from a jar file that is specified in the classpath variable, the JVM won't load that class until your running program will explicitly need that class (or if you load that class explicitly from your code - the same idea). The only problem that can appear when you have a very long classpath, is the time needed for classpath checking before the JVM find the right jar file. But that should not be a problem. If your program behaves well in tests, you should not be worried about this.

Categories