For reasons that I guess are outside the scope of this question, I want to move a program that I have written for use with Java Web Start to stop using JWS and distribute it as an ordinary Jar file instead.
My main problem with this plan is how to figure out where to store files in a nice manner in Java, assuming I'm going to run on different platforms (though I depend on JOGL as well, so there's no great risk of running on horribly esoteric platforms, at least). My program stores various pieces of local data, mostly for caching or "caching-like" purposes -- it's extremely nice to be able to keep it, but it's not a complete disaster if the data is lost.
I currently use the JNLP PersistenceService for this purpose, so moving out of JWS I'll need to figure out some directory to store files in instead. Consider this:
File datadir = new File(System.getProperty("user.home"), ".myprogram");
I figure this works well on Unix and Unix-like platforms, but it's clearly ugly, at least, on some platforms like Windows where I guess I should use the AppData directory or whatever it's called again.
My current line of thought is to use this datadir as a default fall-back everywhere except on known platforms where I replace it with something better, like Windows. The questions I have about this are these:
Is this a reasonable default to begin with? I'm kind-of-fine with this failing on some unknown platforms; I'll just silently disable caching and some extended features if this is the case, but could it fail in some manner that leaves actively bad results?
Is there any good way to figure out I'm on Windows? The best thing I can figure out right now is to match some patterns against os.name, which I guess should work well enough, but is there a better way? I don't intrinsically mind testing with reflection to see if some sun.* packages exist that could help out or something (with the risk of falling back to defaults), if that is good. (Question applies in general to all platforms; are there any somewhat robust idioms for figuring this out in general?)
Is there a good way to figure out the directory to use on Windows? Using static paths seems ugly since I know they can be overridden with registry settings, or be localized and whatnot.
Are there any other platforms I should think of from the outset? My datadir should work fine on OSX, right?
Is there any better alternative altogether?
Consider using the java.util.prefs.Preferences API for this purpose.
If it's just cached data that is replaceable I would just recommend using the temp directory.
See:
new File(File.createTempFile().getParent(), 'my-file-name');
You can set it to be destroyed on your app shut down or just leave it there.
If you want more of a semi-permanent but out of the way storage you may need to care what OS you're on and act accordingly like the answers to this question
Related
I would like to find hardware information such as the hardware ID, manufacturer and type of graphics card, CPU type etc. from within MATLAB. Preferably without installing any additional toolbox or third-party scripts.
I assume this could be done by directly accessing the Java interface.
It's not very easy to do this in a platform-independent way.
I would start by taking a look at cpuinfo from the MATLABCentral File Exchange. This does quite a bit of what you're asking for (although not everything). It does it by including separate code paths for Windows, Unix and Mac, and running the appropriate commands on each.
It's a third-party script, which I know you specified that you didn't want, but it is freely available and authored by a MathWorks developer - and even if you can't use it directly, you could perhaps at least read through it to see how you might proceed to implement things yourself.
I am currently doing a project that needs VirtualBox as third party software. It doesn't need to do very complex stuff, basicly just import an .ova, forward a port, start it, export it again and some cleanup (never more than 1 vm at the time).
This will all be written in Java and needs to work in both linux and windows. My question is, what do you guys think is a better approach? Right now I'm just using the VBoxManage application (which is also exactly the same on both platforms), which means that I can use exactly the same code without any libraries in windows and linux, the only thing that's different is the binary path.
On the other hand, if something in the VBoxManage syntax changes that means it has to be updated and libvirt probably fixes this for you in an easier way.
Point is, I'm not sure what to do, libvirt seems awfully complex and big for something as simple as this and the library itself is also not platform independent =\. Any suggestions?
I will stick with VboxManage. Even when the command syntax changes, it is simpler to manage.
Using libvirt may mean using JNI and more code and more maintenance.
All right, I've hit a bug that has simply confused the bejeebus out of me. I'm looking for ideas about what it could be that I can investigate, because right now, I got nothing. It goes something like this:
I have a standalone Java application that occasionally needs to twiddle the Line-In volume of the computer it's running on (a WinXP machine). It does this by calling a pair of external executables (written in VB6*) that can get and set various component volumes. (They can handle Line-In, Mic, Wave, CD, and the master volume control.)
There are several hundred units in the field, running on hardware (Dell machines) that my company provided and controls. At least several dozen clients are using this feature, and it works perfectly -- except for one instance.
For this one troublemaking machine, it simply doesn't work. I watch the volume sliders when the app is running, and when the volume is supposed to drop, they stay put. When I check the app's log file, it throws no errors, and appears to be executing the code that drops the volume. When I run the executables from the command line, they work perfectly.
I can't vouch for this machine being 100% identical to all the ones that are behaving properly, but we've been buying the same line of Dells for quite some time now; at a bare minimum, it's very, very similar.
So, turning my confusion into a bullet list:
If I'm doing something stupid in the Java code (i.e., not clearing my STDOUT/STDERR buffers), why is it only an issue on this machine?
If there's something broken in the VB6 executables, why do they work on every other machine and on this machine from the command line?
If there's some sort of hardware oddity on this machine, what sort of oddity could cause the volume control executables to fail only when called from within a Java application?
I am very confused. I do not like being confused. Anybody have any suggestions that may lead to my enlightenment?**
-* -- I know, I know, VB6, 1998 called and they want their obsolescent proprietary bug generator back, etc. Wasn't my decision. But the code works. Usually.
-** -- Insert Buddhism joke here.
Update Edit: Customer service may have stumbled onto something; it may be something to do with client configuration settings in the database. New evidence suggests that either something's misconfigured for that client or my software is doing something stupid in response to a specific configuration. And the problem may be more widespread than we thought, due to this particular feature not being as commonly used as I thought.
Responding to the comments:
Debugger: Theoretically possible, but looks like a massive headache given our setup.
High Verbosity Logging, Java: Good idea this, particularly given than the problem may be more widespread than I originally believed. Time to start revisiting some assumptions. And possibly clubbing them. Like baby seals.
High Verbosity Logging, VB6: A possibility; will need to be rolled-into the high-verbosity Java logging to trap the output, since my VB6-fu is so pitiably weak I don't know how to output text to a file. But, yeah, knowing whether or not the script is even getting called would be valuable.
Window Event Viewer: Not familiar with this tool. May have to correct that.
PATH problem: Doesn't feel likely; the Java code constructs a relative path to the executable that doesn't look like it's relying on any environment variables.
My thanks for the suggestions people have provided; at the very least, you've gotten my brain moving in directions that feel promising.
Solution Edit: And the winner is ... That's Not A Bug, That's A Feature! A feature gone horribly, horribly wrong. A feature that will now be neutered so as to stop bothering us.
A batch of invalid assumptions kept me from seeing it sooner, not the least of which was "I don't need to tool the code with more debug statements -- the statements already in there are telling me all I need to know!" DaDaDom, if you'd like to turn your comment into an answer, there's a shiny checkmark in it for you.
Thanks to everybody who chimed in with a suggestion. Now if you'll excuse me, my head is late for a meeting with my desk.
Here goes an answer:
Can you create a version of the software with verbose logging or could you even debug the code? At least then you can tell if it's in the java or the VB part.
Hmmmm. I've been told that executing programs from Java is either easy or hard. The easy part is starting them up. The hard part is dealing with the I/O streams (see my earlier question on using Runtime.exec()). Maybe the VB program is doing or expecting something weird on these particular machines that the Java code isn't working with properly.
edit: I also found a link to Jakarta Commons Exec:
Rationale
Executing external processes from Java is a well-known problem area. It is inheriently platform dependent and requires the developer to know and test for platform specific behaviors, for example using cmd.exe on Windows or limited buffer sizes causing deadlocks. The JRE support for this is very limited, albeit better with the new Java SE 1.5 ProcessBuilder class.
Reliably executing external processes can also require knowledge of the environment variables before or after the command is executed. In J2SE 1.1-1.4 there is not support for this, since the method, System.getenv(), for retriving environment variables is deprecated.
There are currently several different libraries that for their own purposes have implemented frameworks around Runtime.exec() to handle the various issues outlined above. The proposed project should aim at coordinating and learning from these initatives to create and maintain a simple, reusable and well-tested package. Since some of the more problematic platforms are not readily available, it is my hope that the broad Apache community can be a great help.
Have you considered the possibility that the authenticated user may not have permission to edit volume settings on the workstation? Does the program run correctly if you run as an 'Administrator'?
Assume I have a webpage where people submit java source code (a simple class).
I want to compile and run the code on my server, but naturally I want to prevent people from harming my server, so how do I disable java.io.* and other functions/libraries of my choice?
A regexp on the source code would be one way, but it would be "nicer" if one could pass some argument to javac or java.
(This could be useful when creating an AI competition or something where one implements a single class, but I want to prevent tampering with the java environment.)
If you are in complete control of the JVM, then you can use security policies to do this. It's the same approach taken by web browsers when they host applets.
http://java.sun.com/j2se/1.5.0/docs/guide/security/permissions.html
Hope this helps.
Depending on your intent, you might be able to speak with Nick Parlante, who runs javabat.com - it does pretty much exactly what you're describing. I don't know whether he's willing to share his solution, but he might be able to give you some specific help.
My advice is don't do it. At least, don't do it unless you are willing and prepared to accept the consequences of the machine that runs your server being hacked. And maybe other machines on the same network.
The Google App Engine uses an approach where classes are white listed - that is, they are probably either not loaded, or the classes themselves changed and the libraries recompiled, so that no IO, or other system calls can be made. perhaps you could try this by recompiling a jvm like http://jikesrvm.org/.
You can always run the code in a custom classloader. This allows you full control about what you will accept to load.
Is there a way to deploy a Java program in a format that is not reverse-engineerable?
I know how to convert my application into an executable JAR file, but I want to make sure that the code cannot be reverse engineered, or at least, not easily.
Obfuscation of the source code doesn't count... it makes it harder to understand the code, but does not hide it.
A related question is How to lock compiled Java classes to prevent decompilation?
Once I've completed the program, I would still have access to the original source, so maintaining the application would not be the problem. If the application is distributed, I would not want any of the users to be able to decompile it. Obfuscation does not achieve this as the users would still be able to decompile it, and while they would have difficulty following the action flows, they would be able to see the code, and potentially take information out of it.
What I'm concerned about is if there is any information in the code relating to remote access. There is a host to which the application connects using a user-id and password provided by the user. Is there a way to hide the host's address from the user, if that address is located inside the source code?
The short answer is "No, it does not exist".
Reverse engineering is a process that does not imply to look at the code at all. It's basically trying to understand the underlying mechanisms and then mimic them. For example, that's how JScript appears from MS labs, by copying Netscape's JavaScript behavior, without having access to the code. The copy was so perfect that even the bugs were copied.
You could obfuscate your JAR file with YGuard. It doesn't obfuscate your source code, but the compiled classes, so there is no problem about maintaining the code later.
If you want to hide some string, you could encrypt it, making it harder to get it through looking at the source code (it is even better if you obfuscate the JAR file).
If you know which platforms you are targeting, get something that compiles your Java into native code, such as Excelsior JET or GCJ.
Short of that, you're never going to be able to hide the source code, since the user always has your bytecode and can Jad it.
You're writing in a language that has introspection as part of the core language. It generates .class files whose specifications are widely known (thus enabling other vendors to produce clean-room implementations of Java compilers and interpreters).
This means there are publicly-available decompilers. All it takes is a few Google searches, and you have some Java code that does the same thing as yours. Just without the comments, and some of the variable names (but the function names stay the same).
Really, obfuscation is about all you can get (though the decompiled code will already be slightly obfuscated) without going to C or some other fully-compiled language, anyway.
Don't use an interpreted language? What are you trying to protect anyway? If it's valuable enough, anything can be reverse engineered. The chances of someone caring enough to reverse engineer most projects is minimal. Obfuscation provides at least a minimal hurdle.
Ensure that your intellectual property (IP) is protected via other mechanisms. Particularly for security code, it's important that people be able to inspect implementations, so that the security is in the algorithm, not in the source.
I'm tempted to ask why you'd want to do this, but I'll leave that alone...
The problem I see is that the JVM, like the CLR, needs to be able to intrepert you code in order to JIT compile and run it. You can make it more "complex" but given that the spec for bytecode is rather well documented, and exists at a much higher level than something like the x86 assembler spec, it's unlikely you can "hide" the process-flow, since it's got to be there for the program to work in the first place.
Make it into a web service. Then you are the only one that can see the source code.
It can't be done.
Anything that can be compiled can be de-compiled. The very best you can do is obfuscate the hell out of it.
That being said, there is some interesting stuff happening in Quantum Cryptography. Essentially, any attempt to read the message changes it. I don't know if this could be applied to source code or not.
Even if you compile the code into native machine language, there are all sorts of programs that let you essentially decompile it into assembly language and follow the process flow (OlyDbg, IDA Pro).
It can not be done. This is not a Java problem. Any language that can be compiled can be decompiled for Java, it's just easier.
You are trying to show somebody a picture without actually showing them. It is not possible. You also can not hide your host even if you hide at the application level. Someone can still grap it via Wireshark or any other network sniffer.
As someone said above, reverse engineering could always decompile your executable. The only way to protect your source code(or algorithm) is not to distribute your executable.
separate your application into a server code and a client app, hide the important part of your algorithm in your server code and run it in a cloud server, just distribute the client code which works only as a data getter and senter.
By this even your client code is decompiled. You are not losing anything.
But for sure this will decrease the performance and user convenience.
I think this may not be the answer you are looking for, but just to raise different idea of protecting source code.
With anything interpreted at some point it has to be processed "in the clear". The string would show up clear as day once the code is run through JAD. You could deploy an encryption key with your app or do a basic ceasar cipher to encrypt the host connect info and decrypt at runtime...
But at some point during processing the host connection information must be put in the clear in order for your app to connect to the host...
So you could statically hide it, but you can't hide it during runtime if they running a debugger
This is impossible. The CPU will have to execute your program, i.e. your program must be in a format that a CPU can understand. CPUs are much dumber than humans. Ergo, if a CPU can understand your program, a human can.
Having concerns about concealing the code, I'd run ProGuard anyway.