Proguard obfuscated jar won't launch - java

I was having trouble running my obfuscated jar, I got the "Java Virtual Machine Launcher" message "A Java Exception has occurred" when I try to run it. (This error is a popup, not on the command line) I tried running from the command line and printing the stacktrace from the jvm console and didn't see any exceptions.
So I did a little troubleshooting: I disabled shrinking, obfuscating AND optimizing so that the output (should be) the same as the input. The output jar turned out to be a few KB less than the input. I extracted both jars, decompiled the .class files and compared the source of every single file and the MANIFEST.MF and they were all the same*!
I'm using ProGuard 4.10, JDK 1.7.0_25 x64 and Windows 8. I'm building a fairly elaborate JavaFX program and I believe I properly configured ProGuard- but that shouldn't matter anymore if shrinking, obfuscating and optimizing are all disabled, right? Here are the notes that ProGuard gives me:
Note: duplicate definition of library class [netscape.javascript.JSException]
Note: duplicate definition of library class [netscape.javascript.JSObject]
Note: com.javafx.main.Main accesses a field 'HKEY_LOCAL_MACHINE' dynamically
Note: com.javafx.main.Main accesses a field 'HKEY_LOCAL_MACHINE' dynamically
Note: com.javafx.main.Main accesses a declared method 'reset()' dynamically
Note: com.javafx.main.Main$2 accesses a field 'ERROR_MESSAGE' dynamically
When I first tried obfuscating, I skipped com.javafx.main.** but I still got those messages. Any help would be greatly appreciated. I had no problems running my jar before it processed by ProGuard. Thanks.
*EDIT: When doing a binary comparison, the manifest files differ (the original is longer) but doing an ASCII comparison both files are identical. All other files are completely identical. The difference between the two MANIFEST.MF files is PC vs. UNIX line breaks.
*EDIT2: I ran the file with the -jar option, and I did get an explicit exception!
java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
From com.javafx.main.Main here is the use of ERROR_MESSAGE and HKEY_LOCAL_MACHINE:
int ERROR_MESSAGE = ERROR_MESSAGE_Field.getInt(null);
Method showMessageDialogMethod = jOptionPaneClass.getMethod("showMessageDialog", new Class[] { componentClass, Object.class, String.class, Integer.TYPE });
showMessageDialogMethod.invoke(null, new Object[] { null, this.val$string, "JavaFX Launcher Error", new Integer(ERROR_MESSAGE) });
...
Field HKEY_LOCAL_MACHINE_Field = winRegistryClass.getField("HKEY_LOCAL_MACHINE");
int HKEY_LOCAL_MACHINE = HKEY_LOCAL_MACHINE_Field.getInt(null);
String path = (String)mGet.invoke(null, new Object[] { new Integer(HKEY_LOCAL_MACHINE), "Software\\Oracle\\JavaFX\\" + version, "Path" });

The jar was signed; I made an unsigned version and it obfuscated correctly!

Related

Get File Version of .exe in java on Linux

Question - Get File Version of .exe in java on Linux for some strange client.
Solution -
I used JNA library to read file version using Java. Given below code is running fine on windows platform but it is throwing below error on Linux docker image.
"Unable to load library 'version': Error loading shared library libversion.so: No such file or directory Error loading shared library libversion.so: No such file or directory Native library (linux-x86-64/libversion.so) not found in resource path..".
private String GetFileVersion(String filePath) {
File fileToCheck = new File(filePath);
short[] rtnData = new short[4];
int infoSize = Version.INSTANCE.GetFileVersionInfoSize(fileToCheck.getAbsolutePath(), null);
Pointer buffer = Kernel32.INSTANCE.LocalAlloc(WinBase.LMEM_ZEROINIT, infoSize);
try {
Version.INSTANCE.GetFileVersionInfo(fileToCheck.getAbsolutePath(), 0, infoSize, buffer);
IntByReference outputSize = new IntByReference();
PointerByReference pointer = new PointerByReference();
Version.INSTANCE.VerQueryValue(buffer, "\\", pointer, outputSize);
VerRsrc.VS_FIXEDFILEINFO fileInfoStructure = new VerRsrc.VS_FIXEDFILEINFO(pointer.getValue());
rtnData[0] = (short) (fileInfoStructure.dwFileVersionMS.longValue() >> 16);
rtnData[1] = (short) (fileInfoStructure.dwFileVersionMS.longValue() & 0xffff);
rtnData[2] = (short) (fileInfoStructure.dwFileVersionLS.longValue() >> 16);
rtnData[3] = (short) (fileInfoStructure.dwFileVersionLS.longValue() & 0xffff);
return String.format("%s.%s.%s.%s", rtnData[0], rtnData[1], rtnData[2], rtnData[3]);
} catch (Exception exception) {
return null;
} finally {
Kernel32.INSTANCE.GlobalFree(buffer);
}
}
I will start by answering the question that you asked, though I doubt it is what you actually need to know.
The types of different executable file formats are encoded in the first few bytes of the file. For example, ELF files (executables, shared libraries) are described in this Wikipedia page.
So there are a number of ways to find out what kind of executable in Java:
Write some code that reads the first few bytes and decodes the file header information, as per the format described in the Wikipedia link above.
Find an existing Java library that does this and work out how to do this. (Google for "java file magic library" and see what you can find.)
Read about the Linux file command and write some Java code to run file on each library and parse the output.
What I think you actually need to do is a bit different:
Locate the file or files in the file system that the Java is looking for: apparently libversion.so or linux-x86-64/libversion.so. (The file could well be a symlink. Follow it.)
Run file on each file to check that it is the right kind of library. They need to be 32 or 64 bit corresponding the JVM you are running, and the correct ABI and ISA for the platform.
Check that the files are where the JVM expects to find them. The JVM searches for libraries in directories listed in the "java.library.path" system property. You can (if necessary) set the path using a -Djava.library.path=... JVM option.
See "java.library.path – What is it and how to use" for more information on library loading.
(There is absolutely no need to do step 2 "from" or "in" Java.)
I think I have finally worked out what you are doing.
The Version you are using is actually coming from the package com.sun.jna.platform.win32. It is not part of the JNA library (jna.jar). I think it is actually part of jna-platform.jar. If I understand things correctly, that is the generated JNA adapter library for the Windows COM dlls.
If I have that correct, you would actually need the Windows COM native libraries compiled and built for the Linux platform to do what you are trying to do.
AFAIK, that's not possible.
So how could you make this work? Basically you need to do one of the following:
Look for an existing pure Java library for extracting the version information from a Windows ".exe" file. I don't think it is likely that you will find one.
Find the specification for the Windows ".exe" file format and write your own Java code to extract the version information. I haven't looked for the spec to see how much work it would be.
Then you rewrite the code that you added your question to use the alternative API.
The "libversion" file that I mentioned in my other answer is not relevant. It is something else. It is a red herring.

ClassNotFoundException while replacing java 6 rmi w/ java 8 [duplicate]

The following method :
private void startServer() { // snippet that starts the server on the local machine
try {
RemoteMethodImpl impl = new RemoteMethodImpl();
Naming.rebind( "Illusive-Server" , impl );
}catch(Exception exc) {
JOptionPane.showMessageDialog(this, "Problem starting the server", "Error", JOptionPane.ERROR_MESSAGE);
System.out.println(exc);
}
}
throws this exception :java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: Interfaces.RemoteMethodIntf
When i start my project, i am greeted with the message in JOptionPane saying problem starting the server and then the above exception. What could be the reason for this ?
I don't understand why does the last statement of exception says class not found exc when i have imported the right packages
There are four cases of this exception.
When exporting: you didn't run 'rmic' and you didn't take the steps described in the preamble to the Javadoc for UnicastRemoteObject to make it unnecessary.
When binding: the Registry doesn't have the stub or the remote interface or something they depend on on its classpath.
when looking up: the client does't have these things on its classpath.
When calling a remote method: you either sent something to the server of a class not present on its CLASSPATH, or received something from the server (including an exception) of a class not on your CLASSPATH: in both cases possibly a derived class or interface implementation of a class or interface mentioned in the remote interface's method signature.
This is case 2. The Registry can't find the named class.
There are several solutions:
Start the Registry with a CLASSPATH that includes the relevant JARs or directories.
Start the Registry in your server JVM, via LocateRegistry.createRegistry().
Use dynamic stubs, as described in the preamble to the Javadoc of UnicastRemoteObject. However you may then still run into the same problem with the remote interface itself or a class that it depends on, in which case 1-3 above still apply to that class/those classes.
Ensure that case (4) above doesn't occur.
Use the codebase feature. This is really a deployment option and IMO something to be avoided at the initial development stage.
Remote Server Error:RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: mathInterface
The error very simple to solve to be perform following steps:
For example your java file consider D drive
Start rmiregistry D drive( example D:\start rmiregistry)then don't start rmiregistry on the other drives, it will yield the above error
(Wherever your file is, start rmiregistry)
I will try to explain it as better as possible what I did:
1st. I declared the classpath variable like follow:
set classpath=%classpath%
set classpath=C:\compiler
set classpath=C:\compiler\libro\cap07\rmi\hello\Hello.java
set classpath=C:\compiler\libro\cap07\rmi\hello\Server.java
set classpath=C:\compiler\libro\cap07\rmi\hello\Client.java
(All in one lineset:
set classpath=%classpath%;C:\compiler;C:\compiler\libro\cap07\rmi\hello\Hello.java;C:\compiler\libro\cap07\rmi\hello\Server.java;C:\compiler\libro\cap07\rmi\hello\Client.java)
(I'm not sure if the .java files were nesesary, but I also wrote them for doubts).
2nd. I compilered with the line javac -d C:\compiler Hello.java Server.java Client.java. Where C:\compiler is the root directory like src on Eclipse IDE.
3rd. I ran the start rmiregistry line. (and don´t matter where you run it, it's the same).
4th. I ran:
start java -classpath C:\compiler -Djava.rmi.server.codebase=file:C:\compiler/ libro.cap07.rmi.hello.Server
You already know C:\compiler, but you need define packages address on the last to that the command can find the .class files. Open any .java file and copy the package address without packages sentense. You will see when you open the src directory (in my case C:\compiler), you find all directory sequence created. When this command line is created correctly, no matter where you will run it, C:, D:, src, anywhere it wil run.
5th. And finally, I ran the Client class with:
java -classpath C:\compiler libro.cap07.rmi.hello.Client
In conclusion, if the classpath variable won't created or it's to created wrong or the sentence of 4th point is not addressed well the JVM throws the same or similar error. Search there!
(Sorry my english).
You can launch rmiregistry from anywhere but you have to make sure that the compiled classes are already in your classpath. For example:-
E:\ARMSRemoteUpdater\WebContent\WEB-INF\classes>set classpath=%classpath%;E:\ARMSRemoteUpdater\WebContent\WEB-INF\classes <ENTER>
E:\ARMSRemoteUpdater\WebContent\WEB-INF\classes>c: <ENTER>
C:\>rmiregistry
And the above should work fine.
In general, if you launch rmiregistry from the root location of the compiled classes (above example it is E:\ARMSRemoteUpdater\WebContent\WEB-INF\classes), that will work because . (dot - current directory) is already set in your classpath.
But as soon as you remove . (dot - current directory) from your classpath, the above working condition will also fail.
Hope I have explained in details.
I got this same issue, and a different solution worked for me. I was running two different IntelliJ projects, with a copy of the interface in each project. One of them was in a package, and the other one wasn't, and that was what was causing this error.
Solutions:
Make sure the interface copies aren't in a package.
Make sure the interface copies have the exact same package name.

TCLBLEND FAILURE - Centos 6.4

I have been trying to use a home grown test tool and after doing an update to Centos 6.4, I am no longer able to run the tcl based tool. I am getting the following error and I have no internet access on this server. Kindly advise how do I solve this problem?
Thanks
"XpUtils::iload -d /usr/local/testtool/repo/package/linux-glibc2.3-x86_64/lib/tcljava1.4.1 tclblend" failed:
couldn't load file "/usr/local/testtool/repo/package/linux-glibc2.3-x86_64/lib/tcljava1.4.1/libtclblend.so": libjava.so: cannot open shared object file: No such file or directory
while executing
"error "\"XpUtils::iload -d $dir tclblend\" failed:\n $errMsg""
(procedure "loadtclblend" line 168)
invoked from within
"loadtclblend /usr/local/testtool/repo/package/linux-glibc2.3-x86_64/lib/tcljava1.4.1"
("package ifneeded java 1.4.1" script)
invoked from within
"package require java"
("eval" body line 1)
invoked from within
"eval package require $pkg"
("foreach" body line 2)
invoked from within
"foreach pkg $pkgList {
set ::${pkg}Version [eval package require $pkg]
}"
(file "/usr/local/testtool/testtool" line 165)
If you read the error message trace, you'll see that it says that this is all caused by:
libjava.so: cannot open shared object file: No such file or directory
The first steps would then be to ensure that you've got a version of Java actually installed, to check that it includes the file libjava.so, and that the file has been indexed by the system shared library catalog.
It might also be worth checking that all its dependencies are also present and that you've got the architecture for the Tcl library and the Java library matched (e.g., both 32-bit) as those can cause odd failures when they go wrong.

new Rengine(...); fails without error

I'm trying to set up JRI with Eclipse on a Windows 7 x64 system. I tried it once on my Laptop and it worked. Now on my Desktop it fails although everything of the R, rJava and JRI installation is exactly the same.
I set the JRI and R Paths correctly to:
C:\Program Files\R\R-2.15.1\library\rJava\jri;C:\Program Files\R\R-2.15.1\bin\x64
Also I set R_DOC_DIR etc in Eclipse.
Every time I try to run new Rengine(...); it fails without any error or exception. Debugging revealed an: <terminated, exit value: 10>C:\Program Files\Java\jre6\bin\javaw.exe (01.10.2012 18:00:31)
Is there anything I can try? It really bothers me that it works an my Laptop but not on my Workstation despite the same settings everywhere.
Edit: The code that is used to get the Rengine object.
public static Rengine getRengine(){
if (re == null) createRengine();
return re;
}
public static void createRengine(){
if (re!=null) return;
try{
if (!Rengine.versionCheck()) {
System.err.println("** Version mismatch **");
System.exit(1);
}
String[] arguments = {"--save"};
re=new Rengine(arguments, false, null);
if (!re.waitForR()) {
System.out.println("Cannot load R");
return;
}
}
catch (Exception e){
e.printStackTrace();
}
}
Edit: The last time i tried it i got an errormessage (creating of the REngine worked, this happened never before), R was missing a registryentry. After installing R 2.15.1 again it suddenly worked. Now after a restart it's the same like before. The program crashes at the creation of the REngine.
I was having the exact same problem. It turns out I had unchecked the box that asks to make a registry entry with the R version number. Once I let the installer run with that box checked, it seemed to work.
I would make sure your regedit looks like this:
Next up: getting this working in a portable way...
I am using R 3.2.2 and eclipse Mars on Windows 10 x64.
I faced the described issue today and tried around a bit. Finally, I found the root cause in the build path. Please check whether the following conditions are fulfilled:
1.) The following Java libraries from the JIRI folder on your hard disk shall be included as (user) libraries:
JIRI.jar
REngine.jar
JRIEngine.jar
2.) The native library jiri.dll is located in the subfolder "i386" for x86, whereas for x64 it is available in the subfolder "x64". The relevant one shall be added as separate native library location to the Java Build Path of the eclipse project. Otherwise, the file may not be considered as it is not located in the main JIRI folder.
Best regards
Philipp

Java RMI Remote Interface Tutorial - error: unmarshalling arguments [duplicate]

The following method :
private void startServer() { // snippet that starts the server on the local machine
try {
RemoteMethodImpl impl = new RemoteMethodImpl();
Naming.rebind( "Illusive-Server" , impl );
}catch(Exception exc) {
JOptionPane.showMessageDialog(this, "Problem starting the server", "Error", JOptionPane.ERROR_MESSAGE);
System.out.println(exc);
}
}
throws this exception :java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: Interfaces.RemoteMethodIntf
When i start my project, i am greeted with the message in JOptionPane saying problem starting the server and then the above exception. What could be the reason for this ?
I don't understand why does the last statement of exception says class not found exc when i have imported the right packages
There are four cases of this exception.
When exporting: you didn't run 'rmic' and you didn't take the steps described in the preamble to the Javadoc for UnicastRemoteObject to make it unnecessary.
When binding: the Registry doesn't have the stub or the remote interface or something they depend on on its classpath.
when looking up: the client does't have these things on its classpath.
When calling a remote method: you either sent something to the server of a class not present on its CLASSPATH, or received something from the server (including an exception) of a class not on your CLASSPATH: in both cases possibly a derived class or interface implementation of a class or interface mentioned in the remote interface's method signature.
This is case 2. The Registry can't find the named class.
There are several solutions:
Start the Registry with a CLASSPATH that includes the relevant JARs or directories.
Start the Registry in your server JVM, via LocateRegistry.createRegistry().
Use dynamic stubs, as described in the preamble to the Javadoc of UnicastRemoteObject. However you may then still run into the same problem with the remote interface itself or a class that it depends on, in which case 1-3 above still apply to that class/those classes.
Ensure that case (4) above doesn't occur.
Use the codebase feature. This is really a deployment option and IMO something to be avoided at the initial development stage.
Remote Server Error:RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: mathInterface
The error very simple to solve to be perform following steps:
For example your java file consider D drive
Start rmiregistry D drive( example D:\start rmiregistry)then don't start rmiregistry on the other drives, it will yield the above error
(Wherever your file is, start rmiregistry)
I will try to explain it as better as possible what I did:
1st. I declared the classpath variable like follow:
set classpath=%classpath%
set classpath=C:\compiler
set classpath=C:\compiler\libro\cap07\rmi\hello\Hello.java
set classpath=C:\compiler\libro\cap07\rmi\hello\Server.java
set classpath=C:\compiler\libro\cap07\rmi\hello\Client.java
(All in one lineset:
set classpath=%classpath%;C:\compiler;C:\compiler\libro\cap07\rmi\hello\Hello.java;C:\compiler\libro\cap07\rmi\hello\Server.java;C:\compiler\libro\cap07\rmi\hello\Client.java)
(I'm not sure if the .java files were nesesary, but I also wrote them for doubts).
2nd. I compilered with the line javac -d C:\compiler Hello.java Server.java Client.java. Where C:\compiler is the root directory like src on Eclipse IDE.
3rd. I ran the start rmiregistry line. (and don´t matter where you run it, it's the same).
4th. I ran:
start java -classpath C:\compiler -Djava.rmi.server.codebase=file:C:\compiler/ libro.cap07.rmi.hello.Server
You already know C:\compiler, but you need define packages address on the last to that the command can find the .class files. Open any .java file and copy the package address without packages sentense. You will see when you open the src directory (in my case C:\compiler), you find all directory sequence created. When this command line is created correctly, no matter where you will run it, C:, D:, src, anywhere it wil run.
5th. And finally, I ran the Client class with:
java -classpath C:\compiler libro.cap07.rmi.hello.Client
In conclusion, if the classpath variable won't created or it's to created wrong or the sentence of 4th point is not addressed well the JVM throws the same or similar error. Search there!
(Sorry my english).
You can launch rmiregistry from anywhere but you have to make sure that the compiled classes are already in your classpath. For example:-
E:\ARMSRemoteUpdater\WebContent\WEB-INF\classes>set classpath=%classpath%;E:\ARMSRemoteUpdater\WebContent\WEB-INF\classes <ENTER>
E:\ARMSRemoteUpdater\WebContent\WEB-INF\classes>c: <ENTER>
C:\>rmiregistry
And the above should work fine.
In general, if you launch rmiregistry from the root location of the compiled classes (above example it is E:\ARMSRemoteUpdater\WebContent\WEB-INF\classes), that will work because . (dot - current directory) is already set in your classpath.
But as soon as you remove . (dot - current directory) from your classpath, the above working condition will also fail.
Hope I have explained in details.
I got this same issue, and a different solution worked for me. I was running two different IntelliJ projects, with a copy of the interface in each project. One of them was in a package, and the other one wasn't, and that was what was causing this error.
Solutions:
Make sure the interface copies aren't in a package.
Make sure the interface copies have the exact same package name.

Categories