I would like to know how can I check if a compiled Java class contains debug symbols. The problem is that I compile an application from ant with debug="on", but a specific JVM throws an exception: it says that the debug symbols are missing.
Thanks.
If you run javap -v on the class file, you will see the debug information that is present in the file.
It is worth compiling a simple test class with different -g option settings and looking at the results with javap.
If, you need to know exactly how javap presents the information, it is it is best for you to try it out in your Java installation. The output from the javap command may vary between different Java versions.
The most important thing a class file with debug information will contain is the LineNumberTable which maps bytecode instructions to source line numbers and the LocalVariableTable which tells the debugger where your local variables, including arguments to a method reside inside the VM during execution.
Related
I am trying to run a Java application which has many dependencies. In the past I have use the following command to launch the application
java -cp "program.jar:jar1.jar:jar2.jar:jar3.jar:[...]" program
However as the list of dependencies have grown, I have moved them into an arguments file, the contents of this file are:
-cp "\
program.jar:\
jar1.jar:\
jar2.jar:\
jar3.jar:\
[...]"
And I am running the application with
java #arguments-file program
Everything up to this point works fine.
Sometimes I end up with beta versions of program.jar, they share all of the same dependencies, but program.jar is renamed program-beta.jar.
So to run the jar the following command would be used
java -cp "program-beta.jar:jar1.jar:jar2.jar:jar3.jar:[...]" program
or more specifically, I would use an environment variable, so that the same script can be used, and the variable would be set to either program.jar, or program-beta.jar, depending on the circumstance
java -cp "$PROGRAM_JAR:jar1.jar:jar2.jar:jar3.jar:[...]" program
Now that I am using an arguments file I was hoping to be able to be able to do something like:
java -cp "$PROGRAM_JAR" #arguments-file program
However using -cp twice causes one of the two to be ignored, resulting in a java.lang.ClassNotFoundException exception.
Is there any way around this that allows me to specify one jar file by name, but abstract away all of the others so that my java command isn't thousands of characters?
This will be running entirely on Linux, so any command line "magic", such as using grep is fine, so long as the resulting code is easily readable
You could just write two bash scripts production.sh and beta.sh that contain a reference on program.jar and program-beta.jar, respectively.
Also, the classpath can contain wildcards (see man-page), so if you can ensure that on disk exists only one of the two versions, you can write it like this:
java -cp "program*:jar1.jar:jar2.jar:jar3.jar:[...]"
In the long term, you might think about building/running it with Maven or Gradle, depending on your requirements.
As a total noob in Java faced with the task of making this program work asap, unfortunately I'm stuck on a loop after consuming the basic bibliography.
The scenario is a 32-bit Linux machine (Ubuntu 16), which has installed both OpenJDK 8 and 11.
And a Java Software where tree . yields
- shiftone-jrat.jar // <-- Special jar because it's outside "lib"?
- fooModule
- foo.class
- foo.java
- ...
- barModule
- bar.class
- bar.java
- ...
- ui
- Main.class
- Main.java // <-- Special Code because it has "main()"
- ...
- lib
- jogl.jar
- vecmath.jar
- gluegen-rt.jar
- ...
- run.bat
- .classpath
The presence of run.bat files suggest that it was compiled in Windows, and after opening .classpath one can note the process was managed from the Eclipse IDE.
As far as I understand Java is very portable so there is no need to recompile the files, we only need to run it.
The only command that has worked without errors is
java -jar shiftone-jrat.jar
But after a quick Google search one can note that jrat is only a profiler.
Thus, the relevant call has to be
java ui.Main
Nevertheless, that yields noClassDefFoundError: the first thing it can complain about before termination is a package called 'vecmath' which is part of our jars in ./lib. Therefore the option cp is added to the command java, like this
java -cp "lib/*" ui.Main"
In this case the problem is that ui.Main itself is not found, so the option is passed a new argument like this:
java -cp ".:lib/*" ui.Main"
Up to this point the previous questions on the same topic here on StackOverflow are very informative. For this particular case they are not sufficient, as the previous command opens a (blank) window that reports the following error:
no gluegen-rt in java.library.path
Where java.library.path includes common root places (e.g. /usr/lib/jni, /usr/lib, /lib and /usr/java/packages/lib).
Please note that there is a .jar called gluegen-rt.jar at ./lib, the same folder that made the previous error vanish by providing a jar called vecmath.jar.
Without fully understanding what .jars are, I downloaded libgluegen2 (and perhaps also jogamp,or it is included? sorry, I don't remember) from ubuntu apt.pkgs (which is the only one I've found, i.e. the "2"), and replaced the
lib/gluegen-rt.jar file with the jar from
/usr/share/java/gluegen2-2.3.2-rt.jar.
Again, I ran
java -cp ".:lib/*" ui.Main"
And now the NoClassDefFoundError mentions gluegen/runtime/DynamicLookupHelper.
A quick (cd /usr/share/java ; grep -r "DynamicLookupHelper") shows that jogl2.jar also matches and thus I also overwrite
lib/jogl.jar file with the jar from
/usr/share/java/jogl2.jar.
Finally the NoClassDefFoundError error is thrown again, this time because there is no such thing as javax.media.opengl, which is often used in the program java's files at imports.
A quick Google search yields that Java's implementation of OpenGL had "some" changes at "some" point in time, thus the lines
javax.media.opengl should be changed to
com.jogamp.opengl to comply with our "newest" version.
I made the changes but then some other lines were broken, so finally I appear to be faced with either (1) looking for the "right" jogamp and/or gluegen or (2) continue the migration. There may be 5k lines.
Questions such as: Is there any other option I'm missing? Is the whole procedure correct? Where are old versions available? Can I leverage the xml-styled .classpath file?
Thanks
My goal
We need to pass -Xpkginfo:always arguments to javac compiler. We are using javac 1.7.0_25. -Xpkginfo is available for this version says java doc.
Expected result: package-info.class files shall be generated
Actual result : javac compiler is crashing :
An exception has occurred in the compiler (1.7.0_25). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport) after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report. Thank you.
java.lang.NullPointerException
at com.sun.tools.javac.comp.Enter.visitTopLevel(Enter.java:291)
at com.sun.tools.javac.tree.JCTree$JCCompilationUnit.accept(JCTree.java:459)
at com.sun.tools.javac.comp.Enter.classEnter(Enter.java:258)
at com.sun.tools.javac.comp.Enter.classEnter(Enter.java:272)
at com.sun.tools.javac.comp.Enter.complete(Enter.java:484)
at com.sun.tools.javac.comp.Enter.main(Enter.java:469)
at com.sun.tools.javac.main.JavaCompiler.enterTrees(JavaCompiler.java:929)
at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:824)
at com.sun.tools.javac.main.Main.compile(Main.java:439)
at com.sun.tools.javac.main.Main.compile(Main.java:353)
at com.sun.tools.javac.main.Main.compile(Main.java:342)
at com.sun.tools.javac.main.Main.compile(Main.java:333)
at com.sun.tools.javac.Main.compile(Main.java:76)
at com.sun.tools.javac.Main.main(Main.java:61)
What I've tried so far
It works with java 1.8, but unfortunately, we can't upgrade our java compiler because we still have old java code.
EDIT
Used javac -X to make sure 1.7.0_25 has -Xpkginfo argument available. Answer is yes :
PS C:\SVN\products\faa_mx\vs2017.install2> javac -X
-Xlint Enable recommended warnings
-Xlint:{all,cast,classfile,deprecation,dep-ann,divzero,empty,fallthrough,finally,options,overrides,path,processing,rawtypes,serial,static,try,unchecked,varargs,-cast,-classfile,-deprecation,-dep-ann,-divzero,-empty,-fallthrough,-finally,-options,-overrides,-path,-processing,-rawtypes,-serial,-static,-try,-unchecked,-varargs,none} Enable or disable specific warnings
-Xbootclasspath/p:<path> Prepend to the bootstrap class path
-Xbootclasspath/a:<path> Append to the bootstrap class path
-Xbootclasspath:<path> Override location of bootstrap class files
-Djava.ext.dirs=<dirs> Override location of installed extensions
-Djava.endorsed.dirs=<dirs> Override location of endorsed standards path
-Xmaxerrs <number> Set the maximum number of errors to print
-Xmaxwarns <number> Set the maximum number of warnings to print
-Xstdout <filename> Redirect standard output
-Xprint Print out a textual representation of specified types
-XprintRounds Print information about rounds of annotation processing
-XprintProcessorInfo Print information about which annotations a processor is asked to process
-Xprefer:{source,newer} Specify which file to read when both a source file and class file are found for an implicitly compiled class
-Xpkginfo:{always,legacy,nonempty} Specify handling of package-info files
Also tried with 1.7.0_80, same crash :
An exception has occurred in the compiler (1.7.0_80).
java.lang.NullPointerException
at com.sun.tools.javac.comp.Enter.visitTopLevel(Enter.java:291)
at com.sun.tools.javac.tree.JCTree$JCCompilationUnit.accept(JCTree.java:459)
at com.sun.tools.javac.comp.Enter.classEnter(Enter.java:258)
at com.sun.tools.javac.comp.Enter.classEnter(Enter.java:272)
at com.sun.tools.javac.comp.Enter.complete(Enter.java:484)
at com.sun.tools.javac.comp.Enter.main(Enter.java:469)
at com.sun.tools.javac.main.JavaCompiler.enterTrees(JavaCompiler.java:929)
at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:824)
at com.sun.tools.javac.main.Main.compile(Main.java:439)
at com.sun.tools.javac.main.Main.compile(Main.java:353)
at com.sun.tools.javac.main.Main.compile(Main.java:342)
at com.sun.tools.javac.main.Main.compile(Main.java:333)
at com.sun.tools.javac.Main.compile(Main.java:76)
at com.sun.tools.javac.Main.main(Main.java:61)
Alternative solution
Would that make sense to use javac 1.8 and use the command line javac -source 1.7 -target 1.7 MyClass.java?
With java 1.7, it looks like that if you pass -Xpkginfo:always to javac, it only accepts package-info.java empty files. If you pass non-empty files, we get the crash.
With 1.8, javac is able to deal with empty and non empty files in one command line.
So, the workaround with 1.7 is to call javac multiple time, once with all empty package-info.java files, and another time with non-empty files.
Can arguments for a class be passed the following way?
java cs123.Learn -mode train -algorithm even_odd -model_file speech.even_odd.model -data speech.train -task classification
Here, cs123 is the package within which the different java files and their compiled versions are located. I have already compiled the .java files using the following command
javac -cp commons-cli-1.2.jar cs123\*.java
To make things clear, the structure of the .java and .jar files are
lib
|--cs362
| |--all the java files including Learn.java
|--commons-cli-1.2.jar
I am running the command prompt from the lib folder. What worries me is that from java documentation and other sources the format for passing arguments is simply an array of strings and for options it can be seen from java documentation too. Using the above run time java execution, I get the
java.lang.ClassNotFoundException: org.apache.commons.cli.OptionBuilder
but if I execute,
java -cp commons-cli-1.2.jar cs123.Learn -mode train -algorithm even_odd -model_file speech.even_odd.model -data speech.train -task classification
I get the following error
Unrecognized option: -mode
Error: Could not create the Java Virtual Machine
Error: A fatal exception has occured. Program will exit.
I understand that java tries to associate anything with a - associated with it as a predefined option, -mode not being the one it recognizes. but at the same time the .jar file is there to do it's job. For research purposes, the commons-cli-1.2.jar file is associated with several methods, two of them being commons/cli/Option and commons/cli/OptionBuilder.
I am having to do this because the instruction is to run the program using
java cs123.Learn -mode train -algorithm even_odd -model_file speech.even_odd.model -data speech.train -task classification
I have made a test with commons-cli with the -mode in option. It compile and run as expected. So I can make sure with you that you can using that option.
I am standing in java folder to run the command, my folder structure:
java
|--upwork
| |--Main.java
|--commos-cli-1.2.jar
For your problem: I see that your command only point classpath to commons-cli lib and not point to the location of your package. Refer to this answer your command should start with: java -cp .;commons-cli-1.2.jar ...
If this does not help, please upload your code to get help or you can create a simple test like mine to check this out.
Can arguments for a class be passed the following way?
I don't think so for the good reason that what you're trying to pass with your "-naming" are program arguments. Program arguments are retrieved in your app with the String[] args of your main and in Java you don't have String index in arrays.
If you want to achieve what you want, you could still do it but you would have to implement the logic in your program. Firstly, you would need to get all the args in your program and then implement the logic by building a map for example and process this map.
As an example, you could say that if any argument (i.e args[0]) starts by "-" it means that it's a key for your map and that the following argument (i.e. args[1]) is the associated value.
Edit: I haven't used commons-cli and I may be completely wrong but from a quick research online, I think the library is offering you the logic to build commands to execute in command line once your application is running.
I add the path of jdk in the environment variable "path", my position is on the directory of the application: "C:\Users\20900994t\Desktop\applicationArbre_2_1\src\applicationarbre"
I have 4 .java files .
I tried 2 methodes.
The first method were:
1. "javac Main.java" 2. "java Main"
The second method were:
1. "javac *. java" 2. "java Main.java"
These methods generate all of the files . classes of all the classes I have, but at the command line it shows me that the purpose of the other classes are not recognized and when I did "java Main", it shows me "NoClasseDefFoundError"
Actually, those method works well in environment Net Beans, however I need to execute it on command line with .bat file .
Thank's
I suspect you're running it like this:
// In directory applicationarbre
$ java Main
You should be running it like this, in the parent directory:
$ java applicationarbe.Main
You say you've tried several solutions, but you haven't explained what you've tried, or what happened when you tried them, which makes it hard to help you further.
Basically, you need to tell Java the fully-qualified name of the class you want to launch, and that class has to be available on the classpath, which is "the current directory" by default. Anything more than that and you'll need to give us more information.
Not like this:
java applicationarbre/Main
but like this:
java applicationarbre.Main
As for the classpath, maybe in your case this will be enough (if you are in the correct base directory below which are your classfiles):
java -cp . applicationarbre.Main
first compile the class in which main method resides
C:\foldername>javac ClassName.java
then run with statement
C:\foldername>java ClassName
hope it will work :)