In my java class I have
System.setProperty("test", drinks);
In my Ant build file I am able to execute the jave class.
How can I use the name "test" to get the result ${drinks} in Ant ??
The only way this is possible is if you use the attribute fork="false" (false being the default value) in the java Ant task. That is, if your Java program is executed in the same JVM as Ant. Otherwise, your Java program will be executed in a separate process and none of the system properties it sets will vbe accessible to Ant. Beware, though, that executing a non-forked Java program may (and often will) have undesired side effects on the rest of the Ant build.
If the property is set at the command line e.g. ant -Dtest=drinks it will be available from the build system as ${test}, however if you're calling this property by means of executing Java code, you will need to find a way to get the value out from the spawned Java process into a new variable, usually using a combination of System.out.println(...) and <exec ...> tasks's outputproperty and parsing as needed.
Related
Our tool (http://plse.cs.washington.edu/daikon) calculates program invariants by inserting instrumentation into the Java byte codes for a program. The user code is instrumented during runtime via the normal ClassFileTransformer::transform method.
It is also necessary to track value flows through JDK methods. Thus, we need to instrument the Java runtime as well. We cannot use transform, because hundreds of runtime methods are loaded prior to the first time we get control at transform.
Prior to Java 9, we handled this in an offline step that reads rt.jar, instruments its methods, and writes out a modified version as dcomp-rt.jar. The user placed dcomp-rt.jar on the bootclasspath to ensure our modified Java runtime methods were loaded instead of the standard ones. The user program invocation would look something like:
java -cp .:.../daikon/daikon.jar \
-Xbootclasspath/p:.../daikon/java/dcomp_rt.jar:.:.../daikon/daikon.jar \
-javaagent:.../daikon/java/dcomp_premain.jar={various dcomp arguments} \
{user program} {user program arguments}
Now to Java 9+. Our first approach was to read in and instrument the class files within the Java runtime jmod files (via the new jrt:/ file system) and create a dcomp_rt.jar as before. The problem we are experiencing is that we cannot get the system to use the contents of this jar instead of jrt:/java.base (for example). We tried various --module-path and -Xbootclasspath (only /a is available now, might be part of problem) options to no avail. Still hoping there might be a way to do this?
If not, I'm guessing we need to make modified versions of each of the interesting runtime jmods and then use a --patch-module argument for each of them. Would this ensure our modified code is loaded instead of the standard runtime?
Any thoughts/suggestions?
Well it looks like --patch-module does the trick. I made the same dcomp_rt.jar but with only classes from java.base.jmod. Then used:
--patch-module java.base={full path}/dcomp_rt.jar
Running java with -verbose:class showed all base classes being loaded from my jar.
Is this the best way to accomplish my goal?
Today I'm trying to use the system property in my code .When I enter ./gradlew -Dorg.gradle.project.env=demo test ,the NullPointExcepetion happens,though I println env in script successfully!Then I try another way , entering ./gradlew -Denv=demo test and my code get the env set in command line successfully .So my question is What's the defference between "-Dorg.gradle.project.env=demo" and "-Denv=demo" in gradle?P.s. This link(12.2. Gradle properties and system properties in https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_properties_and_system_properties) told me to use org.gradle.project to set system property.I guess when you use org.gradle.project, you should use another method to get system property ,not using
System.getProperty("env")
I guess when you use org.gradle.project, you should use another method to get system property, not using System.getProperty("env")
You're right. This two syntaxes are different and serve different purposes.
The latter one, -Denv is a standard way of passing system properties in Java world. If you run java -help you'll see:
-D<name>=<value> set a system property
So, when you use it, env system property becomes available via System.getProperty("env") and it's value will be demo.
The first one -Dorg.gradle.project.env is actually a system property too! It's obvious after reading the lines above. However, it sets a system property named org.gradle.project.env, not just env. So, unless your test expect this name, it won't work. And your tests must no expect this name, because they should, generally, be unaware of the build tool.
What Gradle docs says is:
Gradle offers a variety of ways to add properties to your build. With the -D command line option you can pass a system property to the JVM which runs Gradle. The -D option of the gradle command has the same effect as the -D option of the java command.
Gradle can also set project properties when it sees specially-named system properties or environment variables. This feature is very useful when you don’t have admin rights to a continuous integration server and you need to set property values that should not be easily visible, typically for security reasons. In that situation, you can’t use the -P option, and you can’t change the system-level configuration files. The correct strategy is to change the configuration of your continuous integration build job, adding an environment variable setting that matches an expected pattern. This won’t be visible to normal users on the system.
If the environment variable name looks like ORG_GRADLE_PROJECT_prop=somevalue, then Gradle will set a prop property on your project object, with the value of somevalue. Gradle also supports this for system properties, but with a different naming pattern, which looks like org.gradle.project.prop.
Differently saying, Gradle allows you to set project proprties by providing system properties with special names, and that is what you did. You've set a Project's property named env to a value demo by providing a system property with a name org.gradle.project.env. This property is available in you build script via project.env and can be used to tweak builds in various ways.
I have to run a java task, with a very large number of classpath (1000, totaling 150k characters if concatenated).
The problem is that java returns an error when I try to execute this class:
/jdk/JAVA8/bin/java: Argument list too long
The error code is 7
I've tried to put the classpaths using "export CLASSPATH=CLASSPATH:....." and so I shouldn't specify them through the -cp java parameter, but it returned the same error.
I'm pretty sure that the problem revolves round a classpath's limit, because if I delete some of the classpath, the error disappears (but then I will have logical errors in the execution, because I need all the classpaths)
You could use classpath wildcards. Especially if many of your jars/class files are in the same directory, this would help a lot.
It could be environment variable size limit or command-line size limit as well rather than javac classpath arg limit.
javac takes arguments from file input as well. You can add all your arguments to this file and pass this file argument to command. Refer this for more.
You didn’t hit a java-specific limitation, but a system dependent limit. This is best illustrated by the fact, that the attempt to set the CLASSPATH variable fails as well, but setting an environment variable via export name=value in the shell isn’t related to Java.
As said by others, you could try to use wildcards for jar files within the same directory, but you have to care that Java does the expansion rather than the shell, as in the latter case, it would again yield a too long command line. So you have to escape the * character to ensure it will not be processed by the shell.
javac supports reading the command line arguments from an external file specified via #filename, but unfortunately, the java launcher doesn’t support this option.
An alternative would be to create symbolic links pointing to the jar files, having shorter paths and specifying these. You could even combine the approaches by creating one directory full of symbolic links and specifying that/directory/* as class path.
But there seems to be a logical error in the requirement. In a comment, you are mentioning “code analysis” and an analyzing tool should not require having the code to analyze in its own application class path. You can access class files via ordinary I/O, if you want to read and parse them. In case you want to load them, e.g. for using the builtin Reflection, you can create new ClassLoader instances pointing to the locations. So the tool doesn’t depend on the application class path and could read the locations from a configuration file, for example.
Using distinct class loaders has the additional advantage that you can close them when you’re done.
JVM does not limit classpath length. However, there is a hard OS limit on command line length and environment variables size.
On Linux check getconf ARG_MAX to see the limit.
On older kernel versions it is only 128KB. On newer kernels it is somewhere around 2MB.
If you want to set really long classpaths, you may need a JAR-Manifest trick. See this question for details.
I simply want to modify the directory where the program is run. Normally, it's run from the project root, which annoys me a little bit, because testing the program out can be quite annoying, since my program generates files and folders where it is being run.
A JavaExec task has a property called JavaExec#workingDir, which would be this exact property I wanted to modify to something different of my choice.
My question is: How do I modify the gradle run task in order to access this property?
You can access a property of a task by using tasks.<TaskToModify>.property = YourValue.
So, in this case, you would have to do this:
File runningDir = new File('build/run/')
runningDir.mkdirs()
tasks.run.workingDir = runningDir
The File#mkdirs() call is neccessary, since if the directories do not exist, the call to your system-dependent java executable will cause a error.
So I have a java project with multiple java files.
I know that is almost straight forward to start a java application using batch file. But that is for a pretty simple java program with a single class.
However I am wondering if it is possible to do that with in a scale of a project that you usually create using eclipse. A large project with multiple packages, classes and multiple java files.
My try was to write a script and apply on the main class as following
set path = C:\Program Files\Java\jdk1.7.0_25\bin
javac -classpath twitter/twitter4j-stream-3.0.5.jar;twitter4j-core-3.0.5.jar" sourcepath="lib/twitter4j-core-4.0.1.jar;lib/twitter4j-core-4.0.1.jar;lib/twitter4j-stream-4.0.1.jar;svm_light_lib Program.java
java Program
However when I start the .bat file it automatically closes.
Any Ideas ?
Thanks in advance
First, never overwrite the environment variable path, not even
temporarily. Append your folder instead: set "path=%path%;%mypath%" or set "path=%mypath%;%path%".
(There exists a particular path command but I'm not sure about right syntax: path=%path%;%mypath% with = assignment or path %path%;%mypath% without it).
Use full path to a program if you know it, e.g. "%mypath%\javac".
For better readability, values for -classpath and -sourcepath options are stored to the environment variables mycpth and mysrcp, respectively. Note and use proper " quotation and no spacing around = to avoid any leading and trailing spaces in all set commands.
pause to see all the javac output. Displays the message Press any key to continue . . .
Next code should be (syntax) error-free. However, success depends (among others) on classpath and sourcepath entries visibility as well...
set "mypath=C:\Program Files\Java\jdk1.7.0_25\bin"
set "path=%path%;%mypath%"
set "mycpth=twitter/twitter4j-stream-3.0.5.jar;twitter4j-core-3.0.5.jar"
set "mysrcp=lib/twitter4j-core-4.0.1.jar;lib/twitter4j-core-4.0.1.jar;lib/twitter4j-stream-4.0.1.jar;svm_light_lib"
"%mypath%\javac" -classpath "%mycpth%" -sourcepath "%mysrcp%" Program.java
pause
java Program
However I am wondering if it is possible to do that with in a scale of a project that you usually create using eclipse. A large project with multiple packages, classes and multiple java files.
Of course it is possible!
In this case, I suspect the problem is that you java command doesn't have a "-cp" argument. The java command is probably failing because it can't find twitter classes ... at runtime.
Remember to include "." on the classpath ... or else java won't find the file that you just compiled.
#JB Nizet's suggestion is also very important advice for finding out what is actually happening.