file.separator Java 7 option causes ExceptionInInitializerError - java

We have a TeamCity (7.0.3) agent running on a 64-bit Windows Server 2008 machine. When we recently upgraded the agent to use Java 7 (1.7.0_10) the builds started failing with the following stacktrace:
Error occurred during initialization of VM
java.lang.ExceptionInInitializerError
at java.lang.Runtime.loadLibrary0(Runtime.java:841)
at java.lang.System.loadLibrary(System.java:1084)
at java.lang.System.initializeSystemClass(System.java:1145)
Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: 0
at java.lang.String.charAt(String.java:658)
at java.io.Win32FileSystem.<init>(Win32FileSystem.java:40)
at java.io.WinNTFileSystem.<init>(WinNTFileSystem.java:37)
at java.io.FileSystem.getFileSystem(Native Method)
at java.io.File.<clinit>(File.java:156)
at java.lang.Runtime.loadLibrary0(Runtime.java:841)
at java.lang.System.loadLibrary(System.java:1084)
at java.lang.System.initializeSystemClass(System.java:1145)
The problem seems to be caused by the inclusion of the "-Dfile.separator=\" java option that TeamCity uses in the executable command for the agent. I was able to reproduce the problem by writing a simple "Hello World" class and compiling it on the Windows box and then running the program with the file.separator option (i.e. java -Dfile.separator=\ HelloWorld)
I haven't found any similar bug reports. Has anyone seen anything like this? Has the behaviour of file.separator changed in Java 7?
Furthermore I realise that \ is the default file.separator for Windows anyway so I don't think the agent really needs to use it in the executable command, however I can't see a way in TeamCity to tell the agent not to include it. Is it possible to do this?

Try the JVM command line parameter -Dfile.separator=\/ (i.e., specify both a backward and forward slash).

It looks java.exe now trims trailing \ (back-slash).
I have the following code:
import java.lang.*;
public class test {
public static void main(String[] argz) {
for(String s : argz) {
System.out.println("agg=" + s + "|");
}
System.out.println("prop=" + System.getProperty("prop") + "|");
}
}
I start it with Java 1.7.0_07 and _10:
C:\Java\jdk1.7.0_07\bin\java.exe -cp . -Dprop=z\\ test a\\ b
agg=a\\|
agg=b|
prop=z\\|
and _10
C:\Java\jdk1.7.0_10\bin\java.exe -cp . -Dprop=z\\ test a\\ b
agg=a|
agg=b|
prop=z|
And one more series:
C:\Java\jdk1.7.0_07\bin\java.exe -cp . -Dprop=z\ test a\ b
agg=a\|
agg=b|
prop=z\|
and _10
C:\Java\jdk1.7.0_10\bin\java.exe -cp . -Dprop=z\ test a\ b
agg=a|
agg=b|
prop=z|

Related

How to parse file patterns using Apache commons CLI

I'm trying to parse my command line arguments using the apache commons CLI. It might be a bit heavy handed for the example here, but it makes sense in the context of the program I'm creating. I'm trying to read a file pattern filter, similar to what grep uses to select files to process.
My Argument looks like this:
Program --input *.*
I've written a test program to see what the parser is seeing;
public static void main(String[] args) {
Options options = new Options();
options.addOption(new Option(INPUT_FILTER_SHORT, INPUT_FILTER_LONG, true, INPUT_FILTER_DESCRIPTION));
CommandLineParser parser = new BasicParser();
CommandLine cmd = parser.parse(options, args);
System.out.println(cmd.getOptionValue(INPUT_FILTER_SHORT));
}
This prints out:
.classpath
If I change my arguments to:
Program --input test.txt
I get the output:
test.txt
I'm assuming that I have to do something to tell apache commons what * is not a special character? I can't seem to find anything about this online.
I'm experiencing this on Windows (7). I'm fairly certain it's the *.* which is causing the issue as when I swap to using patterns that don't use *, the expected pattern shows up.
Your problem isn't really to do with Commons CLI, but to do with how the shell and the Java executable together process the parameters.
To eliminate other factors, and see what's going on, use a short Java program:
public class ArgsDemo {
public static void main(String[] args) {
for(int i=0; i<args.length; i++) {
System.out.println("" + i + ": " + args[i]);
}
}
}
Play with java ArgsDemo hello world, java ArgsDemo * etc. and observe what happens.
On UNIX and Linux:
Java does no special processing of *. However, the shell does. So if you did:
$ mkdir x
$ cd x
$ touch a b
$ java -jar myjar.jar MyClass *
... then MyClass.main() would be invoked with the parameter array ["a","b"] -- because the UNIX shell expands * to files in the current directory.
You can suppress this by escaping:
$ java -jar myjar MyClass * // main() sees ["*"])
(Note that a UNIX shell wouldn't expand *.* to .classpath because this form would ignore "hidden" files starting with .)
On Windows
cmd.exe does not do UNIX-style wildcard expansion. If you supply * as a parameter to a command in Windows, the command gets a literal *. So for example, PKUNZIP *.zip passes *.zip to PKUNZIP.EXE, and it's up to that program to expand the wildcard if it wants to.
Since some release of Java 7, the Java executable for Windows does some wildcard to filename expansion of its own, before passing the parameters to your main() class.
I've not been able to find clear documentation of Java-for-Windows' wildcard expansion rules, but you should be able to control it with quoting, escaping the quotes to prevent cmd.exe interpreting them:
> java.exe -jar myjar.jar MyClass """*.*"""
(Untested as I don't have a Windows box handy, and quoting in cmd.exe is a bit of a beast - do please experiment and either edit the above or leave a comment)

python - JAR works in terminal but not from python

I working on a python 3 script for doing some bench (school purpose). So I need to invoke my JAR.
I use subprocess.check_output for that.
java_out = subprocess.check_output("java -jar my_jar.jar -p input_file", shell=True)
In terminal it works fine, I get the expected output and exit code is 0.
But in python, I get this :
Syntax error. (One of my java exception, but it might not happen in this case)
Traceback (most recent call last):
File "C:/Users/Jeremy/PycharmProjects/bench_bf/bench_script.py", line 41, in <module>
main()
File "C:/Users/Jeremy/PycharmProjects/bench_bf/bench_script.py", line 32, in main
result_list.append(bench(bf_file, stats_file))
File "C:/Users/Jeremy/PycharmProjects/bench_bf/bench_script.py", line 10, in bench
java_out = subprocess.check_output("java -jar my_jar.jar -p input_file", shell=True)
File "C:\Python34\lib\subprocess.py", line 620, in check_output
raise CalledProcessError(retcode, process.args, output=output)
subprocess.CalledProcessError: Command 'java -jar my_jar.jar -p input_file' returned non-zero exit status 5
Process finished with exit code 1
That does not make any sense to me. Can anyone help me ? Thanks !
The full code is following (I've also tried with absolute path) :)
import subprocess
import os
import re
FILE_NAME = "input_file"
JAR_NAME = "my_jar.jar"
TEST_ITER = 5
def bench(bf_file, stats_file):
java_out = subprocess.check_output("java -jar "+ JAR_NAME + " -p " + FILE_NAME, shell=True)
print(java_out)
m = re.search(".*EXEC_TIME : (\d*) ms.*EXEC_MOVE : (\d*)", java_out)
return [m.group(0), m.group(1)]
def init_stats(f):
f.write("Iterations; Exec time; exec move")
def write_file(f):
f.write("+++")
def main():
bf_file = open(FILE_NAME, "w", encoding="utf-8")
stats_file = open("bench-result.csv", "w")
write_file(bf_file)
init_stats(stats_file);
result_list = []
for i in range(0,TEST_ITER):
result_list.append(bench(bf_file, stats_file))
average_time = 0;
for res in result_list:
average_time += res[0]
average_time /= TEST_ITER;
stats_file.write(average_time + ";" + result_list[0][1])
main()
EDIT: I also tried java_out = subprocess.check_output(["java", "-jar", "my_jar.jar", "-p", "input_file"], shell=True), it changes nothing.
EDIT 2: Same result using absolute path or os.system
* SOLUTION *
Since I open the file in write mode, my JAR can't open it, and consider it's empty... Thanks my mate DjNikita :)
My first thought would be that there is something in your environment that is not transferring to the subprocess. Try this and see if it outputs anything that looks relevant
import os
for key in os.environ:
if any(token in key.lower() for token in ['java', 'jre', 'jdk']):
print(key, os.environ[key])
I've had another thought too. Some programs expect their input to be a tty (ie. interactive terminal) and get angry when they're fed in a pipe. Is there anything in your Java program that might cause it to expect a certain type of input stream?
Try specifying the absolute path of the jar file, as it might be that your sub-process isn't running the directory you think it is.
Try running 'dir' and seeing where it returns, for instance. Maybe check that 'java --V' (the version flag? not in a position to check at the moment) returns something indicating that Java ran, rather than an error. Basically, try and get a simple thing running via Python, then extend it.

Is it possible to get the command used to launch the jvm in java?

I would like to know if it is possible to get from code the command used to launch a java program.
E.g. if I launch a java program with:
java -cp lib1:lib2:... -jar mylib.jar com.foo.Bar
I would like to get the exact string (jvm parameters included).
Is it possible?
Comment on the bounty and the question
Thank you all for your responses. Unfortunately, I did not get the answer I was initally looking for. I was hoping there was some portable solution to get the complete java command from within the program itself (including classpath etc.). As it seems there are no portable solution and since I am using Linux I am using the responses of agodinhost and Luigi R. Viggiano to solve my problem. However I give the bounty to rahulroc for the most complete (portable) response. For the rest an upvote for all :)
The below mentioned code should show all JVM parameters, arguments passed to the main method as well as the main class name.
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.List;
public static void main(String[] args) {
RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean();
List<String> jvmArgs = bean.getInputArguments();
for (int i = 0; i < jvmArgs.size(); i++) {
System.out.println( jvmArgs.get( i ) );
}
System.out.println(" -classpath " + System.getProperty("java.class.path"));
// print the non-JVM command line arguments
// print name of the main class with its arguments, like org.ClassName param1 param2
System.out.println(" " + System.getProperty("sun.java.command"));
}
javadoc for getInputArguments
Returns the input arguments passed to the Java virtual machine which
does not include the arguments to the main method. This method returns
an empty list if there is no input argument to the Java virtual
machine.
Some Java virtual machine implementations may take input arguments
from multiple different sources: for examples, arguments passed from
the application that launches the Java virtual machine such as the
'java' command, environment variables, configuration files, etc.
Typically, not all command-line options to the 'java' command are
passed to the Java virtual machine. Thus, the returned input arguments
may not include all command-line options.
You can also take a look at : jps
It's a Java program that is able to get the full command line for all
Java processes, including full class name of main class and JVM
options.
You can find a good summary of various JVM tools, including
Java Application Launcher links to :
ManagementFactory.getRuntimeMXBean() - Returns the managed bean for the runtime system of the Java virtual machine.
getInputArguments() javadoc
determine if JVM is running in debug mode
You can use this to retrieve the VM parameters :
public static void main(String args[]) {
List<String> inputArguments = ManagementFactory.getRuntimeMXBean().getInputArguments();
System.out.println("input arguments = " + inputArguments);
}
However it won't give you all the command line (only gives the JVM arguments, no main class nor parameters). Sample output:
input arguments = [-Dfile.encoding=UTF-8, -XX:-UseTLAB, -Xms2000m, -Xmx2000m, -XX:+PrintCompilation, -XX:+PrintGC]
It only works on Sun Oracle JVM: System.getProperty("sun.java.command")
Additionally, you can have a look at JavaSysMon, it can report command line of active processes. To check which is the current JVM Process check here: How can a Java program get its own process ID?
in a linux machine would be easier to run:
ps -ef | grep java
this command will list all java programs running with it's used parameters.
Not sure about what can be used in a windows environment.
In the task manager on Win2003 you can enable the display of a column that displays the command like it does on linux. Or, you can do it from the command line like so:
wmic.exe PROCESS where "name like '%java%'" get Processid,Caption,Commandline

Matlab + Java: java.lang.ExceptionInInitializerError when trying to use javabuilder

I've been trying to use Matlab's javabuilder package under Windows XP, but I'm getting a strange error when trying to instantiate any javabuilder class. To illustrate the problem, I've created a simple program that prints the MCRROOT and PATH system variables (to check if they're correctly set) and tries to create a MWCharArray:
import com.mathworks.toolbox.javabuilder.*;
import com.mathworks.toolbox.javabuilder.internal.MCRConfiguration;
class Main
{
public static void main(String[] args)
{
System.out.println("MCRROOT: " + System.getenv("MCRROOT"));
System.out.println("PATH: " + System.getenv("PATH"));
System.out.println(MCRConfiguration.isInstalledMCR());
MWCharArray test = new MWCharArray("Test");
}
}
When I execute the program, the output is:
MCRROOT: C:\Program files\MATLAB\MATLAB Compiler Runtime\v710
PATH: C:\Program files\CollabNet Subversion Client;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\Program files\MATLAB\MATLAB Compiler Runtime\v710
false
Exception in thread "main" java.lang.ExceptionInInitializerError
at com.mathworks.toolbox.javabuilder.internal.MCRConfiguration.getMCRRoot(MCRConfiguration.java:77)
at com.mathworks.toolbox.javabuilder.internal.MCRConfiguration$ModuleDir.<clinit>(MCRConfiguration.java:51)
at com.mathworks.toolbox.javabuilder.internal.MCRConfiguration.getModuleDir(MCRConfiguration.java:56)
at com.mathworks.toolbox.javabuilder.internal.MWMCR.<clinit>(MWMCR.java:1447)
at com.mathworks.toolbox.javabuilder.MWUtil.GetUnknownClassID(MWUtil.java:1258)
at com.mathworks.toolbox.javabuilder.MWClassID.<clinit>(MWClassID.java:41)
at com.mathworks.toolbox.javabuilder.MWCharArray.<init>(MWCharArray.java:75)
at Main.main(Main.java:11)
Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(String.java:1937)
at com.mathworks.toolbox.javabuilder.internal.MCRConfiguration$MCRRoot.get(MCRConfiguration.java:70)
at com.mathworks.toolbox.javabuilder.internal.MCRConfiguration$MCRRoot.<clinit>(MCRConfiguration.java:72)
... 8 more
Java Result: 1
First of all, are MCRROOT's and PATH's values correct? I've tried google for finding out how to set MCRROOT, but there are conflicting results: some sources say that I should include de version dir, others say the opposite. Also, why is the isInstalledMCR method returning false? I've double-checked the MCR installation (and even uninstalled and installed it to be sure), so why isn't the library finding it?
Thanks on advance for any help!
Edit: I've also tried setting MCRROOT with no version string, and it also fails.
Just wild guessing! Java is messing around with strings, while your 'mcrroot' contains white spaces. I might change the mcr install path to something like C:\MATLAB\MATLABCompilerRuntime\v710, omitting any white spaces and special characters.
I've found the solution, so I'm post a self answer for future reference: Besides adding the javabuilder.jar to the program's classpath, you also have to add the path to the MCR's runtime libraries to the java.library.path JDK parameter.
My mistake was that, instead of setting the path as the path to the libraries at the MCR installation directory (On my case, C:\MATLAB\MCR\v710\runtime\win32), I copied the runtime directory to my project's dir and used it instead. It seems that the javabuilder library uses the java.library.path variable the guess the MCROOT, what would explain the weird "StringIndexOutOfBoundsException".

How to execute a java .class from the command line

I have a compiled java class:
Echo.class
public class Echo {
public static void main (String arg) {
System.out.println(arg);
}
}
I cd to the directory and enter: java Echo "hello"
I get this error:
C:\Documents and Settings\joe\My Documents\projects\Misc\bin>java Echo "hello"
Exception in thread "main" java.lang.NoClassDefFoundError: Echo
Caused by: java.lang.ClassNotFoundException: Echo
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
Could not find the main class: Echo. Program will exit.
What is the simplest way to get my java code in a form that I can run from the command line as apposed to having to use Eclipse IDE?
Try:
java -cp . Echo "hello"
Assuming that you compiled with:
javac Echo.java
Then there is a chance that the "current" directory is not in your classpath ( where java looks for .class definitions )
If that's the case and listing the contents of your dir displays:
Echo.java
Echo.class
Then any of this may work:
java -cp . Echo "hello"
or
SET CLASSPATH=%CLASSPATH;.
java Echo "hello"
And later as Fredrik points out you'll get another error message like.
Exception in thread "main" java.lang.NoSuchMethodError: main
When that happens, go and read his answer :)
With Java 11 you won't have to go through this rigmarole anymore!
Instead, you can do this:
> java MyApp.java
You don't have to compile beforehand, as it's all done in one step.
You can get the Java 11 JDK here: JDK 11 GA Release
You need to specify the classpath. This should do it:
java -cp . Echo "hello"
This tells java to use . (the current directory) as its classpath, i.e. the place where it looks for classes. Note than when you use packages, the classpath has to contain the root directory, not the package subdirectories. e.g. if your class is my.package.Echo and the .class file is bin/my/package/Echo.class, the correct classpath directory is bin.
You have no valid main method... The signature should be:
public static void main(String[] args);
Hence, in your case the code should look like this:
public class Echo {
public static void main (String[] arg) {
System.out.println(arg[0]);
}
}
Edit: Please note that Oscar is also right in that you are missing . in your classpath, you would run into the problem I solve after you have dealt with that error.
If you have in your java source
package mypackage;
and your class is hello.java
with
public class hello {
and in that hello.java you have
public static void main(String[] args) {
Then
(after compilation)
changeDir (cd) to the directory where your hello.class is.
Then
java -cp . mypackage.hello
Mind the current directory and the package name before the class name.
It works for my on linux mint and i hope on the other os's also
Thanks Stack overflow for a wealth of info.
My situation was a little complicated. I had to do three steps since I was using a .dll in the resources directory, for JNI code. My files were
S:\Accessibility\tools\src\main\resources\dlls\HelloWorld.dll
S:\Accessibility\tools\src\test\java\com\accessibility\HelloWorld.class
My code contained the following line
System.load(HelloWorld.class.getResource("/dlls/HelloWorld.dll").getPath());
First, I had to move to the classpath directory
cd /D "S:\Accessibility\tools\src\test\java"
Next, I had to change the classpath to point to the current directory so that my class would be loaded and I had to change the classpath to point to he resources directory so my dll would be loaded.
set classpath=%classpath%;.;..\..\..\src\main\resources;
Then, I had to run java using the classname.
java com.accessibility.HelloWorld
First, have you compiled the class using the command line javac compiler? Second, it seems that your main method has an incorrect signature - it should be taking in an array of String objects, rather than just one:
public static void main(String[] args){
Once you've changed your code to take in an array of String objects, then you need to make sure that you're printing an element of the array, rather than array itself:
System.out.println(args[0])
If you want to print the whole list of command line arguments, you'd need to use a loop, e.g.
for(int i = 0; i < args.length; i++){
System.out.print(args[i]);
}
System.out.println();

Categories

Resources