What can make Java application platform dependent? - java

I am developing an application and wonder what can cause the app to be platform dependent. For example, using Windows path in the app make it app that runs only in Windows.

There are plenty of things that can get you there:
using JNI to make native calls to OS specific features (like: reading/writing values to the windows registry)
relying on libraries ... that do make such native calls for you
The more subtle version of the same, especially in the context of GUI programming:
relying on specific (non standard) fonts
relying on OS specific plafs
As you have written in the question:
"external" identifiers that only work in a platform specific way, like: filepaths
The good news here: all of that is rather explicit. You have to write your code in a certain way to become platform dependent.
What is much harder, but luckily less common: writing valid Java code ... that in the end, relies on specific implementation details of the underlying JVM. For example threads are mapped to the threads that your OS provides. So, theoretically, there is a chance to write java code that behaves differently on different platforms.
Also note that there are in fact various different JVM implementations that matter in todays business world. Which can again result in different behavior at runtime.
Long story short: don't worry too much. When you follow standard best practices (for example: by avoiding fully hardcoded absolute path names), then your "medium sized" project should not have platform issues. But as soon as you are talking about really large, complex applications, things can be different, in many subtle ways.

Related

Is the Java Virtual Machine included with all Java softwares?

I am new to java. I know that the Java virtual machine is an abstract machine which helps to run the Java programs. So I would like to know if the JVM is included with all Java software, such as Eclipse?
Usually not. Java is used by so many programs that including it with every piece of Java software would use a lot more hard drive space than necessary, and a whole new JVM instance would have to be loaded for each one. Also, every piece of software would have to be updated whenever some security flaw is discovered. Hence, it's often installed just once, often shortly after setting up a new computer or OS installation.
Occasionally, a software package may be developed without assuming the presence of Java on a system; hence, it may include its own. Sometimes it may also need a customized JVM of some kind.
The main reason this is done is simply because Java is used by hundreds of millions, if not billions of devices. If a virtual machine or runtime is not so widespread, I can either convince my users to install it (usually an uphill battle if they're not themselves developers) or just bundle it myself.
If you're familiar with the notion of static and dynamic libraries, the same issues crop up there as well.
You may already know that,
the JVM is not one piece of software. Owners have their implementation, but other can make theirs if it satisfies various practical and contractual claims.
and the abstract specification is a Concrete implementations, which exist on many platforms and come from many vendors, are either all software or a combination of hardware and software and runtime instance hosts a single running Java application.
JVM is more to provide a way to strictly define the external behavior (subsystems, memory areas, data types, and instructions) of implementations which are described in an abstract inner architecture.
So To summarize JVM is the combination of hardware and software But not all Java packages are not included as you asked, fairly It doesn't even understand Java source code.

Questions about JNI on Android

I am planning to create a software that will be compatible with both Windows CE and Android devices.
Nothing has been decided yet, but so far I've imagined that I could write most parts of the program using C++ code that could be reused on these two platforms, except for system-dependant things like threads. C++ is highly recommended for performance in my case.
In the case of system-dependent things I would create interfaces that would be implemented in two different ways, one using the win32 API, and the other one using the linux equivalent. The other parts of the code the logic) would be independent and reused on both platforms.
The only part of the application that would not be written in C++ would be the user interface. Using the Android API on Android platforms, and something else on Windows CE (C#, Java, don't know yet).
I've read that Android is not like other linux distributions because many linux features are not available from native code on it.
So my question is : is it possible to natively create and use sockets, threads, critical sections (and any other system-dependant things) from a native linux api using JNI (i.e the equivalent of the win32 api but for linux) or do i always have to create them into the Java layer and pass them down to the native code ?
I've not yet decided how II am going to build this, i'm just informing myself on the different possibilities.
Thank you.
NDK implemented POSIX (include pthread, mutex) and BSD socket, so you don't necessary create them with java objects.
However, STL support is still crappy IMO, which you may need to pay attention with your own code or porting any dependency libraries.
It is possible to do all of this with JNI, but I would think twice before doing so. Using JNI has its share of liabilities; it will make development and debugging considerably more difficult. You will also end up with a lot of callbacks to Java code to communicate with the GUI. Think of features like visual progress indicators for ongoing operations. And don't forget that in the end, your app's performance may suffer because of the extra indirection required by each JNI call. Be sure to measure performance in either case. JNI, or C++ for that matter, does not automatically make anything faster.
Also, it may be harder than what you think to just "mirror" your app on another operating system. Android, as an operating system, behaves differently not only on the GUI side (it is, for example, nonsense to provide a back button within in an Android app), but also on the inside, with its typical app architecture broken down into Services, Activities and Receivers. It's not just "a different GUI", not at all.
If you have backend functionality that really can and should behave identically on both platforms, then go on, write it in C++ and reuse it on Android via JNI. But it may be easier, and it may be equally or more performant, to just implement it or parts of it from scratch on Android, using Java. Without knowing any details about your project, it is impossible to say.
Why don't you try and implement a simple test app on Android using JNI? Try to use the NDK to send an HTTP request in a background thread and write the respone back to Java as a String. You'll eventually see that it works, but you will also have a better understanding of the difficulties involved.

Determining if a Java app is malware

I am curious about what automatic methods may be used to determine if a Java app running on a Windows or PC is malware. (I don't really even know what exploits are available to such an app. Is there someplace I can learn about the risks?) If I have the source code, are there specific packages or classes that could be used more harmfully than others? Perhaps they could suggest malware?
Update: Thanks for the replies. I was interested in knowing if this would be possible, and it basically sounds totally infeasible. Good to know.
If it's not even possible to automatically determine whether a program terminates, I don't think you'll get much leverage in automatically determining whether an app does "naughty stuff".
Part of the problem of course is defining what constitutes malware, but the majority is simply that deducing proofs about the behaviour of other programs is surprisingly difficult/impossible. You may have some luck spotting particular patterns, but on the whole you can't be confident (and I suspect it's provably impossible) that you've caught all possible attack vectors.
And in the general sphere, catching 95% of vectors isn't really worthwhile when the attackers simply concentrate on the remaining 5%.
Well, there's always the fundamental philosophical question: what is a malware? It's code that was intended to do damage, or at least code that doesn't do what it claims to. How do you plan to judge intent based on libraries it uses?
Having said that, if you at least roughly know what the program is supposed to do, you can indeed find suspicious packages, things the program wouldn't normally need to access. Like network connections when the program is meant to run as a desktop app. But then the network connection could just be part of an autoupdate feature. (Is autoupdate itself a malware? Sometimes it feels like it is.)
Another indicator is if a program that ostensibly doesn't need any special privileges, refuses to run in a sandbox. And the biggest threat is if it tries to load a native library when it shouldn't need one.
But all these only make sense if you know what the code is supposed to do. An antivirus package might use very similar techniques to viruses, the only difference is what's on the label.
Here is a general outline for how you can bound the possible actions your java application can take. Basically you are testing to see if the java application is 'inert' (can't take harmful actions) and thus it probably not mallware.
This won't necessarily tell you mallware or not, as others have pointed out. The app could still do annoying things like pop-up windows. Perhaps the best indication, is to see if the application is digitally signed by an author you trust; if not -- be afraid.
You can disassemble the class files to determine which Java APIs the application uses; you are looking for points where the java app uses the OS. Since java uses a virtual machine, there are well defined points where a java application could take potentially harmful actions -- these are the 'gateways' to various OS calls (for example opening a socket or reading a file).
Its difficult to enumerate all the APIs, different functions which execute the same OS action should require the same Permission. But java's docs don't provide an exhaustive list.
Does the java app use any native libraries -- if so its a big red flag.
The JVM does not offer the ability to run arbitrary code, or use native system APIs; in particular it does not offer the ability to modify the registry (a typical action of PC mallware). The only way a java application can do this is via native libraries. Typically there is no need for a normal application written in java to use native code (unless it needs to use devices).
Check for System.loadLibrary() or System.load() or Runtime.loadLibrary() or Runtime.load(). This is how the VM loads native libraries.
Does it use the network or file system?
Look for use of java.io, java.net.
Does it make system calls (via Runtime.exec())
You can check for the use of java.lang.Runtime.exec() or ProcessBuilder.exec().
Does it try to control the keyboard / mouse?
You could also run the application in a restricted policy JVM (the instructions/tools for doing this are not as simple as they should be) and see what fails (see Oracle's security tutorial) -- note that disassembly is the only way to be sure, just because the app doesn't do anything harmful once, doesn't mean it won't in the future.
This definitely is not easy, and I was surprised to find how many places one needs to look at (for example several java functions load native libraries, not just one).

What is portability? How is java more portable than other languages? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 5 years ago.
Improve this question
I wonder how Java is more portable than C, C++ and .NET and any other language. I have read many times about java being portable due to the interpreter and JVM, but the JVM just hides the architectural differences in the hardware, right? We'd still need different JVMs for different machine architectures. What am I missing here? So if someone writes an abstraction layer for C for the most common architectures, let's say the CVM, then any C program will run on those architectures once CVM is installed, isn't it?
What exactly is this portability? Can .NET be called portable?
Portability isn't a black and white, yes or no kind of thing. Portability is how easily one can I take a program and run it on all of the platforms one cares about.
There are a few things that affect this. One is the language itself. The Java language spec generally leaves much less up to "the implementation". For example, "i = i++" is undefined in C and C++, but has a defined meaning in Java. More practically speaking, types like "int" have a specific size in Java (eg: int is always 32-bits), while in C and C++ the size varies depending on platform and compiler. These differences alone don't prevent you from writing portable code in C and C++, but you need to be a lot more diligent.
Another is the libraries. Java has a bunch of standard libraries that C and C++ don't have. For example, threading, networking and GUI libraries. Libraries of these sorts exist for C and C++, but they aren't part of the standard and the corresponding libraries available can vary widely from platform to platform.
Finally, there's the whole question of whether you can just take an executable and drop it on the other platform and have it work there. This generally works with Java, assuming there's a JVM for the target platform. (and there are JVMs for many/most platforms people care about) This is generally not true with C and C++. You're typically going to at least need a recompile, and that's assuming you've already taken care of the previous two points.
Yes, if a "CVM " existed for multiple platforms, that would make C and C++ more portable -- sort of. You'd still need to write your C code either in a portable way (eg: assuming nothing about the size of an int other than what the standard says) or you'd write to the CVM (assuming it has made a uniform decision for all of these sorts of things across all target platforms). You'd also need to forgo the use of non-standard libraries (no networking, threading or GUI) or write to the CVM-specific libraries for those purposes. So then we're not really talking about making C and C++ more portable, but a special CVM-C/C++ that's portable.
Once again, portability isn't a black and white thing. Even with Java there can still be incompatibilities. The GUI libraries (especially AWT) were kind of notorious for having inconsistent behavior, and anything involving threads can behave differently if you get sloppy. In general, however, it's a lot easier to take a non-trivial Java program written on one platform and run it on another than it is to do the same with a program written in C or C++.
As others have already said, portability is somewhat of a fuzzy concept. From a certain perspective, C is actually more portable than Java. C makes very few assumptions about the underlying hardware. It doesn't even assume that there are 8 bits in a byte, or that negative numbers should be represented using two's complement. Theoretically, as long as you have a Von Neumann based machine and a compiler, you're good to go with C.
In fact, a "Hello world" program written in C is going to work on many more platforms than a "Hello world" program written in Java. You could probably get the same "hello world" program to work on a PDP-11 and an iPhone.
However, the reality is that most real-world programs do a lot more than output "Hello world". Java has a reputation for being more portable than C because in practice, it takes a lot more effort to port real-world C programs to different platforms than real-world Java programs.
This is because the C language is really ANSI-C, which is an extremely general-purpose, bare-bones language. It has no support for network programming, threading, or GUI development. Therefore, as soon as you write a program which includes any of those things, you have to fall back on a less-portable extension to C, like Win32 or POSIX or whatever.
But with Java, network programming, threading, and GUI tools are defined by the language and built into each VM implementation.
That said, I think a lot of programmers also underestimate the progress modern C/C++ has made in regard to portability these days. POSIX goes a long way towards providing cross-platform threading, and when it comes to C++, Boost provides networking and threading libraries which are basically just as portable as anything in Java. These libraries have some platform-specific quirks, but so does Java.
Essentially, Java relies on each platform having a VM implementation which will interpret byte code in a predictable way, and C/C++ relies on libraries which incorporate platform specific code using the preprocessor (#ifdefs). Both strategies allow for cross platform threading, networking, and GUI development. It's simply that Java has made faster progress than C/C++ when it comes to portability. The Java language spec had threading, networking and GUI development almost from day one, whereas the Boost networking library only came out around 2005, and it wasn't until 2011 with C++11 that standard portable threading was included in C++.
When you write a Java program, it runs on all platforms that have JVM written for them - Windows, Linux, MacOS, etc.
If you write a C++ program, you'll have to compile it specifically for each platform.
Now, it is said that the motto of Java "write once, run everywhere" is a myth. It's not quite true for desktop apps, which need interaction with many native resources, but each JavaEE application can be run on any platform. Currently I'm working on windows, and other colleagues are working on Linux - without any problem whatsoever.
(Another thing related to portability is JavaEE (enterprise edition). It is said that applications written with JavaEE technologies run in any JavaEE-certified application server. This, however, is not true at least until JavaEE6. (see here))
Portability is a measure for the amount of effort to make a program run on another environment than where it originated.
Now you can debate if a JVM on Linux is a different environment than on Windows (I would argue yes), but the fact remains that in many cases there is zero effort involved if you take care of avoiding a few gotchas.
The CVM you are talking about is very much what the POSIX libraries and the runtime libraries try to provide, however there are big implementation differences which make the hurdles high to cross. Certainly in the case of Microsoft and Apple these are probably intentionally so in order to keep developers from bringing out products on competing platforms.
On the .net front, if you can stick to what mono provides, an open source .Net implementation, you will enjoy roughly the same kind of portability as Java, but since mono is significantly behind the Windows versions, this is not a popular choice. I do not know how popular this is for server based development where I can imagine it is less of an issue.
Java is portable from the perspective of the developer: code written in Java can be executed in any environment without the need to recompile. C is not portable because not only is it tied to a specific OS in many cases, it is also always tied to a specific hardware architecture once it has been compiled. The same is true for C++. .Net is more portable than C/C++, as it also relies on a virtual machine and is therefore not tied to a specific hardware architecture at compile-time, but it is limited to Windows machines (officially).
You are correct, the JVM is platform-specific (it has to be!), but when you say Java is portable, you are talking about it from a developer standpoint and standard Java developers do not write the JVM, they use it :-).
Edit #Raze2Dust To address your question. Yes, you could. In fact, you could make Java platform-specific by writing a compiler that would generate machine code rather than bytecode. But as some of the other comments suggest, why would you do that? You'd have to create an interpreter that maps the compiled code to operations in the same way the JVM works. So the long and short of it is, absolutely, you definitely could, but why would you?
Java provides three distinct types of portability:
Source code portability: A given Java program should produce identical results regardless of the underlying CPU, operating system, or Java compiler.
CPU architecture portability: the current Java compilers produce object code (called byte-code) for a CPU that does not yet exist. For each real CPU on which Java programs are intended to run, a Java interpreter, or virtual machine, "executes" the J-code. This non-existent CPU allows the same object code to run on any CPU for which a Java interpreter exists.
OS/GUI portability: Java solves this problem by providing a set of library functions (contained in Java-supplied libraries such as awt, util, and lang) that talk to an imaginary OS and imaginary GUI. Just like the JVM presents a virtual CPU, the Java libraries present a virtual OS/GUI. Every Java implementation provides libraries implementing this virtual OS/GUI. Java programs that use these libraries to provide needed OS and GUI functionality port fairly easily.
See this link
You ask if one could write a "C VM". Not exactly. "Java" is a big term used by Sun to mean a lot of things, including both the programming language, and the virtual machine. "C" is just a programming language: it's up to the compiler and OS and CPU to decide what format the resulting binary should be.
C is sometimes said to be portable because it doesn't specify the runtime. The people who wrote your compiler were able to pick things that make sense for that platform. The downside is that C is low-level enough, and platforms are different enough, that it's common for C programs to work fine on one system and not at all on another.
If you combine the C language with a specific ABI, you could define a VM for it, analogous to the JVM. There are a few things like this already, for example:
The "Intel Binary Compatibility Specification" is an example of such an ABI (which almost nobody uses today)
"Microsoft Windows" could also be such an ABI (though a huge and underspecified one), for which Wine is one VM that runs programs written for it
"MS-DOS", for which dosemu is one VM
"Linux" is one of the more popular ones today, whose programs can be run by Linux itself, NetBSD, or FreeBSD
"PA-RISC", for which HP's Dynamo was a JIT-like VM
All of these C VMs are in fact a real machine -- nobody, AFAIK, has ever made a C VM that was purely virtual. This isn't surprising, since C was designed to run efficiently on hardware, so you might as well make it run normally on one system. As HP showed, you can still make a JIT to run the code more efficiently, even on the same platform.
You need the JVM for different architectures, but of course your Java programs run on that JVM. So once you have a JVM for an architecture, then your Java programs are available for that architecture.
So I can write a Java program, compile it down to Java bytecode (which is architecture-agnostic), and that means I can run it on any JVM on any architecture. The JVM abstracts away the underlying architecture and my program runs on a virtual machine.
The idea is that the Java language is portable (or more accurately, the compiled byte-code is portable). You are correct that each VM requires a specific implementation for a given hardware profile. However, once that effort has been made, all java bytecode will run on that platform. You write the java/bytecode once, and it runs on any JVM.
.NET is quite similar, but with a far lower emphasis on the principle. The CLR is analogous to the JVM and it has its own bytecode. Mono exists on *nix, but you are correct that it is not "official".
Portability or as written in Wikipedia, Software Portability is the ability to reuse the same software (code) across multiple environments (OSes). The java JVM is a JVM that can be run on any operating systems it was designed for: Windows, Linux, Mac OSes, etc.
On .NET, it is possible to port your software to different platforms. From Wikipedia:
The design of the .NET Framework
allows it to theoretically be platform
agnostic, and thus cross-platform
compatible. That is, a program written
to use the framework should run
without change on any type of system
for which the framework is
implemented.
And because Microsoft never implemented the .NET framework outside of Windows and seeing that .NET is platform agnostic, Mono has made it possible to run .NET applications and compile code to run in Linux.
For languages such as C++, Pascal, etc. you will have to go to each OS and build it on that platform in order to run it on that platform. The EXE file in Windows isn't the same as the .so in linux (the machine code) since both uses different libraries to talk to the kernel and each OS has its own kernel.
WORE - Write Once Run Everywhere
In reality, this is limited to the platforms that have a JVM, but this covers off the majority of platforms you would wish to deploy to. It is almost a half-way between an interpreted language, and a compiled language, gaining the benefits of both.

Is Java completely Platform Independent?

Is Java completely Platform Independent ?
if not then, what care needs to be taken to see that your code written in Java can run on Multi Platforms. Basically it should work on Targeted Platforms like Windows (Various versions), Linux (all flavors), Mac and Solaris.
While in practice, most compiled byte code is platform independent, my experience in my 12 years of developing on the Java platform has taught me that there are still idiosyncrasies from platform to platform.
For example, while developing a Java 1.4 Swing application for PC and MacOSX the behavior of dialogs was different if the parent frame is null.
Another example might be with working with the file system and files in general. The Java API has methods to help shield the developer from differences in path separators (/ vs \). When writing to a file, it important to use the FileWriter API as intended so that return characters and such are generated properly for the platform that it is being written on.
So while the motto is "write once, run anywhere" my experience has been for production envs it is write once, test, everywhere.
As a result, having strong unit and integration tests can help with this, as you can execute those tests on the various platforms you want to distribute your software.
Despite some minor issues here and there, it is cool to see your code running on Linux, Unix, Windows and MacOSX (BSD Unix) using the same JARs.
As djacobson pointed out, the answer is a qualified "yes". For the most part, Java developers don't have to worry about platform dependencies. However, you may run into problems when you're dealing with APIs that handle traditional OS and platform functions.
When dealing with File I/O, for example, it's easy to make your code platform dependent by ignoring the differences between file/path separators across platforms (i.e. using '\' rather than File.separator).
For the most part, yes. Because Java compiles to bytecode that's executed by its virtual machine, it can generally be expected to behave the same way regardless of the system sitting under the virtual machine.
However. Not even virtual machines are immune to bugs. A quick Google search turns up the following, for example:
http://www.ibm.com/developerworks/java/library/j-diag0521.html
Differences in behavior can vary from JVM to JVM. Hopefully you won't end up with code that depends on any of these cases... but careful research is worthwhile to know what the limitations of your infrastructure are.
You problem will not be executing your code, but more likely the assumptions you have to make about file paths, available external commands (if you need them), necessary file permissions and other external factors that don't really fall under the "Java" problem domain. Unless you're planning on using native code (via JNI) extensively, Java will not be your problem, your environment will.
Which brings us back to the old adage: "write once, test everywhere".
Threading priorities is one thing to consider. Other OS like Solaris for example has more thread priorities than windows. So if you are working heavily on multi-threading, OS is something that may affect the program's behavior.
The main thing to be concerned with is UI code, to make sure that it is represented properly on all the platforms you will be running on.
Another source of possible issues is deploying to different app servers. There might be incompatibility issues between them.
Java other than that is platform independent, This is also one of its weaknesses, since you are coding to a common denominator and many features of each individual OS are not available.
There are very few and they should be pretty obvious. like System.getProperty("os.name") is clearly OS dependant or it wouldn't work. The most common one is System.exec() as it calls another application which is on your system, again you should know if the application you are calling works the same on every system or not (unlikely).
Along with the above concerns, the main problem I had was actually building on different platforms, which may not be what your asking, but may be something to watch out for.
OS X is especially guilty of this when using the Apple Distribution of Java (why anyone would want to put out their own packaging of Java I don't know but that is a separate argument, and on OSX i dont think you have a choice but to use their java). The Libraries that you may or may not be relying on are in completely different directories, eg libraries instead of lib if my memory serves me correctly. And the IBM java I think packages Classes in different Jars in some cases. Ridiculous!!
Hope that helps.

Categories