Having issues decompiling *any* class with Jode - java

I've been staring at this issue for hours now. Any help is appreciated.
I wrote code that uses the Jode decompiler from the "embedded jode jar file". I want to use this version because it is under the Lesser GNU Public License.
Decompiler d = new Decompiler();
try {
FileWriter fw = new FileWriter("c:\\jode.txt");
d.setClassPath("C:\\mycode");
ProgressListener p = new ProgressListener() {
public void updateProgress(double arg0, String arg1) {
System.out.println("inside of progress listener with arg0 = " +arg0+ " and arg1 = " +arg1);
}
};
d.decompile("Test.class" , fw, p);
} catch (Exception ex) {
ex.printStackTrace();
}
and I always get :
Exception in thread "main" java.lang.NoClassDefFoundError: Test.class
at jode.bytecode.ClassInfo.loadInfo(ClassInfo.java:620)
at jode.decompiler.ClassAnalyzer.<init>(ClassAnalyzer.java:86)
at jode.decompiler.ClassAnalyzer.<init>(ClassAnalyzer.java:123)
at jode.decompiler.Decompiler.decompile(Decompiler.java:191)
at testdecompiler.Main.main(Main.java:45)
If I use
jode.decompiler.Main.decompile(...)
things work - but I can't use this class file because it resides in the jode.jar that is only GPL.

I was able to reproduce the problem with all of the different binary versions of jode that are available from their web site. When I built a new version of jode using the mainline from svn, it worked fine. I also saw an entry in one of the jode forums where a user was complaining about the NoClassDefFound problem. His case sounded slightly different, but the jode developer suggested that he use the mainline from svn instead of the prebuild binary.

d.setClassPath("C:\\mycode");
This classpath looks awfully short to me.

This is a guess, as i don't fancy myself with decompiling classes, but i think that u should use
d.decompile("Test" , fw, p);
instead of what u are using now. This could be similar to
Class.forName("ClassName")
without the "class" suffix.

Update: My original assumption was wrong, and to bad, the original exception/ message is thrown away, as far a i can see. The code where JODE fails looks like this:
try {
DataInputStream input = new DataInputStream
(new BufferedInputStream
(classpath.getFile(name.replace('.', '/') + ".class")));
read(input, howMuch);
} catch (IOException ex) {
String message = ex.getMessage();
if ((howMuch & ~(FIELDS|METHODS|HIERARCHY
|INNERCLASSES|OUTERCLASSES)) != 0) {
throw new NoClassDefFoundError(name);
}
Since an IOException has to be thrown to get the NoClassDefFound, check anything regarding your IO subsytsem, e.g. the file.encoding. I guess you should patch JODE to get the detailed error message or debug to this point.

Related

Getting a specific version of an image with Jib (Maven, Docker, testcontainers)

I'm trying to understand a comment that a colleague made. We're using testcontainers to create a fixture:
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.DockerImageName;
public class SalesforceFixture extends GenericContainer<SalesforceFixture> {
private static final String APPLICATION_NAME = "salesforce-emulator";
public SalesforceFixture() {
// super(ImageResolver.resolve(APPLICATION_NAME));
super(DockerImageName.parse("gcr.io/ad-selfserve/salesforce-emulator:latest"));
...
}
...
The commented code is what it used to be. The next line is my colleague's suggestion. And on that line he commented:
This is the part I don't know. The [ImageResolver] gets the specific version of the emulator, rather than the latest. You need a docker-info file for that though, which jib doesn't automatically generate (but I think it can).
This is what I know or have figured so far:
SalesforceFixture is a class that will be used by other projects to write tests. It spins up a container in Docker, running a service that emulates the real service's API. It's like a local version of the service that behaves enough like the real thing that if one writes code and tests using the fixture, it should work the same in production. (This is where my knowledge ends.)
I looked into ImageResolver—it seems to be a class we wrote that searches a filesystem for something:
public static String resolve(String applicationName, File... roots) {
Stream<File> searchPaths = Arrays.stream(roots).flatMap((value) -> {
return Stream.of(new File(value, "../" + applicationName), new File(value, applicationName));
});
Optional<File> buildFile = searchPaths.flatMap((searchFile) -> {
if (searchFile.exists()) {
File imageFile = new File(searchFile + File.separator + "/target/docker/image-name");
if (imageFile.exists()) {
return Stream.of(imageFile);
}
}
return Stream.empty();
}).findAny();
InputStream build = (InputStream)buildFile.map(ImageResolver::fileStream).orElseGet(() -> {
return searchClasspath(applicationName);
});
if (build != null) {
try {
return IOUtils.toString(build, Charset.defaultCharset()).trim();
} catch (IOException var6) {
throw new RuntimeException("An exception has occurred while reading build file", var6);
}
} else {
throw new RuntimeException("Could not resolve target image for application: " + applicationName);
}
}
But I'm confused. What filesystem? Like, what is the present working directory? My local computer, wherever I ran the Java program from? Or is this from within some container? (I don't think so.) Or maybe the directory structure inside a .jar file? Or somewhere in gcr.io?
What does he mean about a "specific version number" vs. "latest"? I mean, when I build this project, whatever it built is all I have. Isn't that equivalent to "latest"? In what case would an older version of an image be present? (That's what made me think of gcr.io.)
Or, does he mean, that in the project using this project's image, one will not be able to specify a version via Maven/pom.xml—it will always spin up the latest.
Sorry this is long, just trying to "show my work." Any hints welcome. I'll keep looking.
I can't comment on specifics of your own internal implementations, but ImageResolver seems to work on your local filesystem, e.g. it looks into your target/ directory and also touches the classpath. I can imagine this code was just written for resolving an actual image name (not an image), since it also returns a String.
Regarding latest, using a latest tag for a Docker image is generally considered an anti-pattern, so likely your colleague is commenting about this. Here is a random article from the web explaining some of the issues with latest tag:
https://vsupalov.com/docker-latest-tag/
Besides, I don't understand why you ask these questions which are very specific to your project here on SO rather than asking your colleague.

Application does not close on 64bit windows when started as runnable jar

I have an application that I developed/tested under 32bit Win (XP and Win7) and eclipse (indigo). I deploy the application using File->Export->Runnable Jar (with "package required libraries into generated JAR"). From there I wrap it into an executable.
I recently noticed that my application can not be closed (by neither the "top right X" nor alt+F4) in 64bit Win7 (32bit Win works fine). I started playing arround in 64bit Win7 and found out, that when started from eclipse, I can close the application. After I exported it into a runnable jar, I can not close it. Every other part of my application works fine (also under 64bit Win7).
I have a shutdown hook running like this:
// initialize JFrame frame;
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
closeApplication();
}
});
frame.setVisible(true);
public void closeApplication() {
while (ConnectionManager.isConnected())
try {
ThreadManager.addMeasRequestPriority(eMeasRequest.DISCONNECT);
Thread.sleep(100);
} catch (InterruptedException e) {}
ConfigurationManager.saveToXML(new File("ressources/settings/startup.xml"));
System.exit(0);
}
I noticed that the GUI is disconnecting, but nothing more (but this means, that closeApplication() is entered). The problem is that I don't have the System.out when I am not running it in eclipse, so I can not see if there is any exception or what is going on. Do you have an idea how I could find the problem (or already know the problem)?
Possible candidates:
System.exit(0) has a different behaviour under 64bit (why would that be and is there an alternative?)
I can not create/write to the given file startup.xml (how can I check that?)
A tiny dwarf inside my 64bit Win7 laptop short circuits some stuff on the motherboard with his iron hammer and thus prevents the application from closing (how could I remove him?)
other
I would appreciate it if you could either tell me, whats going on here or how you would proceed to find out more.
EDIT: Thanks for your fast replies. I have found out, that I get the following exception:
java.io.FileNotFoundException: ressources\settings\startupPlot0.apph (Access denied)
at java.io.FileOutputStream.open(Native Method)
...
But how can this be? This file definitely exists and is written to in non-64bit Win. Also, there are other files in the same directory that are written to just before the exception occurs on that file. They work (I just checked them). The only difference: For the other files, I use a new OutputStreamWriter(new FileOutputStream(File file)) for the other files and a new DataOutputStream(new FileOutputStream(File file)) for this one.
I can verify that system.exit(0) works on 64 bit systems. If I had to guess, My answer would be that you are not disconnecting and you're throwing your Interupted Exception.
My recomendations: Put a system.out.print statement in your catch statement to see if you are catching.. If you are, you know you're problem, if not, you're not disconnecting and sitting in the while loop.
edit: try
FileOutputStream fos = new FileOutputStream("t.tmp"); // t.tmp is the directory&file name
ObjectOutputStream oos = new ObjectOutputStream(fos);
You can use the following to make sure you always call System.exit(0) irrespective of any exceptions:
public void closeApplication(){
try{
while (ConnectionManager.isConnected()){
try{
ThreadManager.addMeasRequestPriority(eMeasRequest.DISCONNECT);
Thread.sleep(100);
}
catch (InterruptedException e){
}
}
ConfigurationManager.saveToXML(new File("ressources/settings/startup.xml"));
}
finally{
System.exit(0);
}
}
Though, you might also be looping infinitely in your while loop.

Which javac.exe is used by ant javac task?

I am facing one problem. I renamed javac.exe on my machine and noticed that ant javac task still works fine.
Does anybody know from where its getting javac.exe?
Actually, I believe, that by default Ant tries to execute the java compiler class directly with this code:
try {
Class c = Class.forName ("com.sun.tools.javac.Main");
Object compiler = c.newInstance ();
Method compile = c.getMethod ("compile",
new Class [] {(new String [] {}).getClass ()});
int result = ((Integer) compile.invoke
(compiler, new Object[] {cmd.getArguments()}))
.intValue ();
return (result == MODERN_COMPILER_SUCCESS);
} catch (Exception ex) {
if (ex instanceof BuildException) {
throw (BuildException) ex;
} else {
throw new BuildException("Error starting modern compiler",
ex, location);
}
}
The code came from here.
Which means that if the library tools.jar is on the current classpath of Ant, it will pickup the class and launch it. This results in the fact that javac.exe can be renamed to whatever you want, it will still work. So to answer your question, it actually executes none of any "javac.exe".
There are other implementations of the Javac task, but I think this is the default one for all compilers 1.3+
You could try starting here and check what is configured in global build.compiler property, it may be pointing somewhere else

FileNotFound (Access is denied) Exception on java.io

Why do I get this error when I run this program? This occurs after random iterations. Usually after the 8000th iteration.
public static void main(String[] args)
{
FileWriter writer = null;
try
{
for(int i = 0; i < 10000; i++)
{
File file = new File("C:\\Users\\varun.achar\\Desktop\\TODO.txt");
if(file.exists())
{
System.out.println("File exists");
}
writer = new FileWriter(file, true);
writer.write(i);
System.out.println(i);
writer.close();
if(!file.delete())
{
System.out.println("unable to delete");
}
//Thread.sleep(10);
//writer = null;
//System.gc();
}
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
if(writer != null)
{
try
{
writer.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
}
After the exception occurs, the file isn't present. That means the it is deleting, but FIleWriter tries to acquire the lock before that, even though it isn't a multi threaded program. Is it because the Windows isn't deleting the file fast enough, and hence the FileWriter doesn't get a lock? If so, then file.delete() method returns before windows actually deletes it?
How do i resolve it, since i'm getting a similar issue during load testing my application.
EDIT 1: Stacktrace:
java.io.FileNotFoundException: C:\Users\varun.achar\Desktop\TODO.txt (Access is denied)
at java.io.FileOutputStream.openAppend(Native Method)
at java.io.FileOutputStream.<init>(FileOutputStream.java:192)
at java.io.FileOutputStream.<init>(FileOutputStream.java:116)
at java.io.FileWriter.<init>(FileWriter.java:61)
EDIT 2 : Added file.exists() and file.delete conditions in the program. and the new stacktrace:
7452
java.io.FileNotFoundException: C:\Users\varun.achar\Desktop\TODO.txt (Access is denied)
at java.io.FileOutputStream.openAppend(Native Method)
at java.io.FileOutputStream.<init>(FileOutputStream.java:192)
at java.io.FileWriter.<init>(FileWriter.java:90)
at com.TestClass.main(TestClass.java:25)
EDIT 3 Thread dump
TestClass [Java Application]
com.TestClass at localhost:57843
Thread [main] (Suspended (exception FileNotFoundException))
FileOutputStream.<init>(File, boolean) line: 192
FileWriter.<init>(File, boolean) line: 90
TestClass.main(String[]) line: 24
C:\Users\varun.achar\Documents\Softwares\Java JDK\JDK 6.26\jdk\jre\bin\javaw.exe (09-Nov-2011 11:57:34 PM)
EDIT 4 : Program runs successfully on different machine with same OS. Now how do i ensure that the app with run successfully in the machine it is deployed in?
On any OS you can have only a certain number of open files/threads at a stretch. You seem to be hitting your OS limit. Try setting file to null inside the loop.
If I understand your stack trace correctly, the exception is coming when trying to create a new FileWriter. It's impossible to know the reason without investigating a bit further.
Return values may tell something. Especially, check what File.delete() returns.
Before trying to create new FileWriter, check what File.exists() returns.
If the previous delete() returns true and the exists() right after it also returns true, in a single-threaded program, then it's indeed something weird.
Edit: so it seems that deletion was successful and the file didn't exist after that. That how it's supposed to work, of course, so it's weird why FileWriter throws the exception. One more thought, try checking File.getParentFile().canWrite(). That is, do your permissions to write to the directory somehow disappear.
Edit 2:
Don't get the error on a different machine with the same OS. Now how do i make sure that this error won't come in the app where it'll be deployed?
So far you have one machine that works incorrectly and one that works correctly. Maybe you could try it on even more machines. It's possible that the first machine is somehow broken and that causes errors. It's amazing how often digital computers and their programs (I mean the OS and Java, not necessarily your program) can be just a "little bit broken" so that they work almost perfectly almost all of the time, but fail randomly with some specific hardware & use case - usually under heavy load - similar to how incorrect multi-threaded programs can behave. It doesn't have to be your fault to be your problem :-)
Frankly, the only way to make sure that errors won't come up in machine X is to run the program on machine X. Unusual stuff such as creating and deleting the same file 8000 times in rapid succession is prone to errors, even though it "should" work. Computers, operating systems and APIs are not perfect. The more unusual stuff you do, the more often the imperfections will realize themselves, because unusual usage is generally less thoroughly tested than everyday operations.
I have had the same issue, a java program (single threaded) that opens, deleted then re-opens the same file continuously.
On some windows systems we get the same issue as reported here, on Linux, Solaris, and various other windows systems it works fine.
Traceing the program with SysInternals Process Monitor (now MS) its clear the delete is done first, at the OS level, and clear the subsequent open fails with PENDING DELETE status.
So there seems to be some slight delay at the OS/NTFS/Disk level before the file is actually deleted, and that seems to be the cause of the random failure in our case.
As a workaround, I changed the .delete() call to instead just write over the top of it new FileWriter(file) and that seems to be working.
The problem did not occur on all systems, one specific model that would always fail, all be it after not fixed number of loops, was a Windows 7 / Dell Lattitude E6420 with WD Smartdrive, whereas my Windows 7 / Dell precision M4600 (with solid state drive) or T3400 with Linux I have never had the issue.
Cheers - Mark
It may be a long shot, but, can you try to work with a file that is NOT directly sitting on the Desktop. Instead of:
"C:\\Users\\varun.achar\\Desktop\\TODO.txt"
Try:
"C:\\Users\\varun.achar\\SomeOtherDirectory\\TODO.txt"
OS may be killing you here with all the Desktop hooks...
EDIT based on the comments:
Are there any scheduled jobs running on the "bad" machine?
Instead of debugging the environment, do you have a sys admin to do that?
Does this work on a clean Windows install? [95% chance it will]
Since the root cause seems to be environment, instead of solving a Windows configuration problem, would you be able to move forward with other tasks, and leave it to someone who keeps the list of discrepancies between the systems?
Can you conditionally try to write to the file ?
Using file.exists and then writing to it, so you can potentially avoid any other issues. Hard to say from this exception.
http://download.oracle.com/javase/6/docs/api/java/io/File.html#exists()
Could you also post a thread dump at that point, just to debug it further.
Please flush the writer, before writing again.
These are the scenerios you should handle before deleting a file http://www.java2s.com/Code/Java/File-Input-Output/DeletefileusingJavaIOAPI.htm
at least check for return value in your program.
Thanks folks for help me out but this is how it got resolved finally.
public static void main(String[] args)
{
FileWriter writer = null;
try
{
for(int i = 0; i < 10000; i++)
{
File file = new File("C:\\tenant-system-data\\abc.txt");
if(!file.getParentFile().canWrite())
{
System.out.println("parent file error");
}
if(file.exists())
{
System.out.println("File exists");
}
int count = 0;
while(count++ < 5)
{
try
{
file.createNewFile();
break;
}
catch(IOException e)
{
try
{
Thread.sleep(100);
}
catch(InterruptedException e1)
{
e1.printStackTrace();
}
}
}
writer = new FileWriter(file, true);
writer.write(i);
System.out.println(i);
writer.close();
if(!file.delete())
{
System.out.println("unable to delete");
}
//Thread.sleep(10);
//writer = null;
//System.gc();
}
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
if(writer != null)
{
try
{
writer.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
}
I just had the same problem (FileWriter & Access Denied).
My guess for the reason: Windows 7 had put a lock on the file because a preview of the file content was shown in an Explorer window (the file was selected in the window).
Solution: I de-selected the file in the Explorer window. And the IOException was gone.
You have delete permission in the directory but not create permission.

JGit/EGit Loading of translation bundle failed en_US

I am running the following code in a JUnit test to test fetching a git repository. I'm writing a test for each of the basic functionality i need from JGit so that then i can implement them in my application. The problem is that i keep getting the following error on the git.fetch() call below:
Loading of translation bundle failed for [org.eclipse.jgit.JGitText, en_US]
org.eclipse.jgit.errors.TranslationBundleLoadingException: Loading of translation bundle failed for [org.eclipse.jgit.JGitText, en_US]
The code sample is below. I verified that the repository paths and everything seems correct. If i put a breakpoint on the fetch call and then run the same command in MSysGit it works.
try {
String remoteName = "origin";
URIish uri = new URIish(repository.getRepositoryDirectory());
saveRemote(repository2.getRepository(), uri, remoteName);
Git git = repository.getGit();
FetchResult r = git.fetch().setRemote(remoteName).call();
assertNotNull("Did not get any result from fetch.", r);
} catch (JGitInternalException ex) {
fail("Failed to do fetch. " + ex.getMessage());
} catch (InvalidRemoteException ex) {
fail("Failed to do fetch. " + ex.getMessage());
} catch (URISyntaxException ex) {
fail("Failed to do fetch. " + ex.getMessage());
}
Thanks!
Okay I figured this out. I had to copy the file JGitText.properties from the binary distribution into the same package in the source code, rename it to JGitText_en_US.properties, and add a whole bunch of properties to it manually that the code used in JGitText.java but were not defined in JGitText.properties.
I searched through the entire source code and all binary files and related docs and found no reference to these new properties, or the properties file being created anywhere. I don't know why the devs don't have localization files in the source code or at least a way to generate then through a build file or something. I mean they must manually have to add them into their source code and just not commit it.
Anyway this was a very annoying issue, there was no documentation on it anywhere on the net (that google revealed anyway) so I thought i would share this as it might help others who ran into the same problem.
I had the same problem, but my fix was a little different. In my case, the problem was related to the OSGI classloader.
Here's a commit that fixes the issue:
https://github.com/diffplug/jgit/commit/3bcc69bde5567ec57ccd6bd065ded0db49f810fb
And here's the rationale behind it:
Loading a ResourceBundle within an OSGi bundle

Categories

Resources