Reconstructing an Executable jar (with Modified Class-Path) from Class Files - java

I'm grading an assignment in Java. Students are asked to implement a Five-In-A-Row (like Tic-Tac-Toe, or two-player Pente) interface which is used by a GUI .java file. These files (interface and GUI) are given to the students in a file called lab2.jar (where they're in cs251/lab2/ under the names GomokuModel and GomokuGUI, respectively), which the students must add to their classpaths. When the project is finished, students are requested to turn in a .java file called Gomoku.java.
One student turned in a .jar, but the command
java -jar Gomoku.jar
responds with
no main manifest attribute, in Gomoku.jar
I figure the student may have forgotten / not known to make a manifest file. I unzip the student's jar and find only .class files. I try to make my own jar from these files:
According to specs, the main must be in Gomoku.java, whose class is Gomoku.class. So I make a manifest.txt file that looks like
Main-Class: Gomoku
Class-Path: lab2.jar
And try to make a .jar out of it using the command
jar cfm myJar.jar manifest.txt *.class lab2.jar
But when I run this using the command
java -jar myJar.jar
I get the following error:
0Exception in thread "main" java.lang.IllegalAccessError: tried to access method cs251.lab2.GomokuGUI.<init>(Lcs251/lab2/GomokuModel;)V from class Gomoku
at Gomoku.main(Gomoku.java:47)
This particular error is giving me trouble. I've never seen anything like it, and my research on the web doesn't turn up anything. Because the error says it's coming from GomokuGUI, which is one of the lab2.jar files, I think the error's on my end. My questions are:
Can I make an executable .jar when I know and have
What goes in the classpath
Where the main should be
A set of relevant class files
If the answer to (1) is yes: Am I going about it in the right way? I have a feeling I'm missing a recompile step somewhere.
In this particular case, I may ask the student to resubmit. And I will download the .jar's I see submitted before due date to make sure they are runnable. But for knowledge's sake (I myself have made .jar files that have had only .class in them and no manifest), is there a way to salvage a working file like the one described above?

From the JRE javadoc:
public class IllegalAccessError
extends IncompatibleClassChangeError
Thrown if an application attempts to access or modify a field, or to
call a method that it does not have access to.
You're getting
0Exception in thread "main" java.lang.IllegalAccessError: tried to access method
cs251.lab2.GomokuGUI.<init>(Lcs251/lab2/GomokuModel;)V from class Gomoku
at Gomoku.main(Gomoku.java:47)
The method it's complaining about is named <init>. That's what Java calls constructors, internally. It's saying that Gomoku.main() tried to issue new GomokuGUI(model) where model is expected to be an instance of GomokuModel, but that this constructor was not accessible. The fact that Gomoku.main() is in a different package from GomokuGUI means the constructor would have to be public for that to work.
You can check that via reflection -- I believe Eclipse can do that for you, actually -- but that's almost certainly what's going on.
So either the student turned in broken code, or you broke it during your attempts to force-fit it into convenience-executable jarfile format. Which was wasted effort in any case, since you can't grade the assignment based on object code and you're going to have to go back and ask for source code anyway.
If you really want to try running the jarfile the student submitted: Go back to the original unmodified jarfile and try just running 'java Gomoku -classpath myJar.jar' where myJar.jar is what the student turned in. If that doesn't work, try 'java Lcs251.lab2.Gomoku -classpath myJar.jar', which is probably the package they intended to put it into given the error message you're getting. If neither of those runs, ask the student what command line they've been using to run it and try that. If THAT doesn't work, then it's time to investigate why.
The whole executable-jar question is a red herring and a waste of time until you know the code actually runs and what the entry point actually is.

Related

Debug compiled Java .class files in VS Code

I'm taking a CS Data Structures course, and I want to try and work with VS Code instead of the current editor that I'm using (BlueJ). However, my work is evaluated based on whether it can satisfy a certain set of tests presented by a compiled tester file (a .class file that I can use to run/check my work), something that VS Code doesn't seem to particularly like.
This tester is what contains the program's main() method, so I either need to use BlueJ (which already supports running compiled classes) or run the file from the command line (something that I know how to do, but have found somewhat tedious) in order to run the method. Is there a way that I could configure a VS Code Java debugger to execute the main() method located within my compiled tester file?
A note: These tester files do not come with editable .java counterparts; if we were able to see what the tester checks for, that would ruin the point of the tester!
Not exactly what you want, But:
For tedious commands, you could set up an alias in your $HOME/.bash_aliases file.
Bash Aliases .
i.e one i aliased earlier :
alias ds="java -cp $HOME/javaWorkScripts/jspDatabaseApp/bin/ FormatTabContents $HOME/VSCODE\ Research/SURFACE-TIDE-JSP-DATABASE-APP-22-DEC-2018.txt "
From now on, you could just type ds in terminal to run the command.
You can decompile and debug the class in IntelliJ easily. Then set break points on main method and check it.
You can decompile the class in VS code easily but I doubt you will be able to debug the .class file in VS Code.

Java on Win server, bat run packages

To begin with, I dont know much Java, but we have some old Java applications on my firm that collects information that runs every night, however recently it stopped working. There is a bat file that, from what I understand, runs all the required packages, however, when I run it, it returns "Could not find or load main class -insert whatever class I put second - "
Code from the .bat file:
java -cp com.spprod.mywysiwyg.NY.jar; mysql-connector-java-3.1.10-bin.jar; com.spprod.mywysiwyg.CalculateDailyStats;
The first one is the whole package, and the second one is the connector, they are both in the same folder, but in the cmd I get the error that it cant find mysql. If I switch order with 2nd and 3rd it says that I cant find "CalculateDailyStats" instead. Is there something wrong with this line of code?
Thanks in advance.
The -cp switch specifies the classpath in java (path where to look for the files). The jars after -cp are separated with semicolon.
Now, I suppose, that you are trying to run com.spprod.mywysiwyg.CalculateDailyStats class. So, maybe the last semicolons are confusing e.g. try the following:
java -cp com.spprod.mywysiwyg.NY.jar;mysql-connector-java-3.1.10-bin.jar com.spprod.mywysiwyg.CalculateDailyStats

Class file creation concepts

I tried a strange experiment.
I created a project in Eclipse. I created Abc.java which has a main method which prints "Hello" to output.
I then built the project using eclipse. A class file named Abc.class was created. I copied that class file to some random location. Then , I navigated to the class file and used the following command to execute it.
java Abc
It printed "Hello" on the console. So far so well. I assume for a simple sysout there are no dependencies a JVM needs to resolve.
Next I created a very complex program in my eclipse for which I had to include 15 different jars(ex slf4j and apache-commons). After building the program in eclipse, I just copied its class files to a different location(not the JARS).
The main method which does all the complex coding was still in Abc.
I hit the command again(this time I followed package structure so I had to call a slightly different command).
java com.great.Abc
I was under the impression that since I hadn't added any jars to classpath in the java command, this code would break down miserably(remember it had a lot of dependencies).
However, its working absolutely fine.
Can someone please explain why?
(Half hour later :|)
Meanwhile I tried another experiment, and this amazes me even more. I mailed all the class files generated through eclipse to a different computer (note that I did not mail the jar files, only the class files generated by eclipse).
And I ran the program over there, hoping that it would break this time.
And guess what, it runs perfectly. Any inputs?
Are the jars required only at compile time?
How would I ensure that the jars I use are needed at runtime while creating a program?
Please explain calmly no matter how stupid the questions seem. :)
In Java, code dependencies are established between classes so when you create a class which just prints a message, your eclipse project setup has no relevance as long as your class is not using any class from the fancy eclipse setup.
Even if your class is referring to other classes it might happen that these classes are not loaded at runtime when the class is not really using them.
Even if you launch a Java program from a jar file which has dependencies to other jar files declared in its manifest, the standard Java launcher will ignore the absence of one or more of these jar files silently and during the program execution it will report failures only if required classes from these missing jar were tried to load.
One case were it is guaranteed that your program will break early is when its superclass is not present at runtime.
The Jar files aside, I actually find it strange enough that it even loaded your Abc class itself, since the JVM would look for com.great.Abc only in a com/great subdirectory of your classpath. I suspect that you, somehow, have some implicit classpath set in your environment or something, which points back to your Eclipse environment, and that the JVM found it there.
To verify this being or not being the case, you can run Java with the -verbose:class option, to make it tell you where it loads classes from:
java -verbose:class com.great.Abc
Eclipse uses the Absolute path to your included jar files.
Even when you move your main class it still works fine

Doesn't find my main class in a jar

I'm developing a program with three classes and also includes some external jar archives and classes. When I run it in Eclipse it works properly, but I need to try with some other programs, so I need to run it at the console. I save all of it in a folder, which contains another two folders, one with the .class created by me and the other one with the .java and .jar archives and a folder with the external classes. I've tried to creat a .jar archive containing this folder and the manifest, where I told where's the main class.
When I run it I receive "Exception in thread "main" java.lang.NoClassDefFoundError", so it doesn't found the class where the main is, but I don't know why. I've tried some different ways to define it at the manifest and changing the classpath and it still doesn't work.
Any solutions or advices?
Thanks!
Try to use JarSplice, it will let you define the main class.
NoClassDefFoundError means that the file existed during compile time, but it was not found during run time. Since there were no compilation issues, the jar was created, but at run time, while using command like java -jar jarfilename fullyqualifiedclassname it threw this exception. Check the classpath variable, validate that you are executing the command from the right folder location in command window.
I had always referred the below link for such errors and it worked for me
http://javaeesupportpatterns.blogspot.in/2012/06/javalangnoclassdeffounderror-how-to.html
when creating a project for example ABC the IDE normally Netbeans creates the source folder and creates the main class as ABC.java which contains the main class. In Netbeans IDE let you mention your main class if it is not ABC or if not you must create an instance of the class you want to run when application executes in ABC.java class.
In one of my projects I ran also in the same situation. The problem was always a missunderstanding of mine with this error message.
The reason in my case was that the computer could not found the declared jar file. The use of the parameter -cp let me became happy. So try
java -jar -cp ./Server.jar
Edit:
I forgot to mention that I had also to mention the full qulified name of class which contains the main class.
This:
The stacktrace is "Exception in thread "main" java.lang.NoClassDefFoundError: /bin/TextClient
looks to me like your Manifest is wrong. To correct it, you can use:
jar -uvfe Server.jar full.name.of.your.MainClass
Note: not the file/path name of some class file!
This will create a MANIFEST that tells that full.name.of.your.MainClass is your main class.
In addition, if your jar contains entries like:
bin/Foo.class
bin/...
you created the JAR file probably from the wrong place (unless your TLD is bin).
If your main class is named org.adepts.Main, then a top level entry should be:
org/adepts/Main.class
(This is where it will be searched.)
I finally solved it by using the Eclipse "Export" option and not creating it manually.

java.lang.NoClassDefFoundError in cmd

I am facing this problem while trying to run my java file by writing java filename ....
I have read on many pages the possible ways this could be corrected but unfortunately I have been unable to correct my problem...
First of all I looked at my environment variables and observed that there was no CLASSPATH set and I had pointed PATH correctly to my jre as well as jdk bin in C:\
Second I am able to run javac filename.java and observe that .class file gets built in the local directory.
While writing javac -classpath . filename works writing java -classpath . filename (without .class) results in the same error.
I just don't know how to run my program in command prompt!!!!
Please do not give me links to the pages which have given the same answers that I have mentioned above as they do not work in my case.....
Please help....
Note that if your class resides in some package mypackage, you need to make sure the class file is inside mypackage/ and do
java -classpath . mypackage.YourClass
There is a bit little information in your post ... as said, a complete example would really help solving this. Some ideas:
Is class named filename? If not, you should make sure to call the right class name in the java command.
if you have strange characters in your class name (basically anything apart from A-Z, a-z, 0-9, _), it could be mangled by your file system and thus lead to java not being able to find it. Make sure that the class name is the same as the file name.
If you use packages, make sure the package names are congruent to your file structure (see latest questions with tag package for some examples).
Is your class public? If not, make it so. (This should give another error, though.)
Stating javac filename.java and java filename are not enough for this really.
We also need to know the contents of the filename.java or at least the first few lines.
This is the expected way to declare a class
public class Filename {
}
This is the way it would have to be to work given your example: java filename
public class filename {
}
This is could exist too, but you are probably just messing with us :)
public class SomethingElse {
}
Overall no matter what the filename is on the filesystem, the class has a name and that is the name that the java command is expecting. I would recommend using the upper case first letter form as it is clearer imo

Categories