I'm currently running my web application on Java1.5 codebase, running it on Tomcat 5.5 and MySql 5. Looking through the list of additions that were added into Java1.6, I have to ask the question, "Is there any compelling reason to move from 1.5 to 1.6?". There seems like an incredible lack of necessary improvements and additions. A lot of changes in Swing (not that interesting). Keep in mind the current web application is stable (-ish) and moving up a version always entails some risk.
Am I missing anything important by not moving up? Is there a good reason to move up?
Faster execution time.
Better dynamic debugging.
Better native look and feel in Swing (not important to web apps).
Supported on Windows Vista (could become important, depending on your platform).
JavaScript integrated into the platform (could be a big deal if you update your webapp).
Better scripting language support (could deploy RoR in theory, if needed).
Lightweight web services platform integrated (might be useful).
Better already integrated JDBC4 support.
In other words, it depends, but generally there's enough to make a compelling argument. There's also enough that you might not benefit from to make a compelling counter argument.
Eventually you will have to change. When you do, if you've made the counter argument to stay the same for too long, you wind up having to fix multiple accumulated historical issues all at once. That can overwhelm a team, so sometimes it is best to stay "just a bit behind" current, but never very out-of-date.
I'm assuming you've looked over the features page, and if you haven't, you should.
Java 5 went "end of service life" in 2009.
The newer VM is faster.
Sun (now Oracle) Java 5 has reached end-of-service-life status on October 30, 2009. That means that Oracle will not do bug- and security-fixes anymore on it, unless you pay for a "Java SE for Business" contract (see the web page for details).
Besides that, Java 6 contains a lot of performance improvements (which might or might not matter for your particular application).
It's usually easier to keep an application up to date if you stay on the most recent version.
(Not bleeding edge, but current).
The transition between 1.5 and 1.7 may require more work than if you make the shift to 1.6 first.
jvisualvm in the JDK is reason enough to upgrade. Allows you to investigate and profile an already running process without any preparation.
Related
I am a hobbyist java programmer using NetBeans IDE. A problem I face with programming in Java is choosing the correct target JRE version. I understand that most of my friends have at least java 6, but few have a totally up-to-date version with which I compile. I know how to compile for a particular target run-time environment on NetBeans; the problem is that by using an earlier target release of Java, the compiler expects code written in that version.
For a specific example, I occasionally use a Java 8 lambda instead of a new Runnable(){}, however the compiler (or at least NetBeans) doesn't accept this 'modern' code. Another example is the use of the diamond operator, or the use of multiple-exception catch statement, neither of which are supported by Java 6. The language evolves and the compiler evolves, but older versions of Java cannot handle the change. To distribute my code, I am forced to use what some might consider outdated code.
My question is: Is it considered good practice or common practice to write Java for an outdated target version to provide compatibility? Is there some form of 'translator' or cross-compiler for Java code?
My question is: Is it considered good practice or common practice to write Java for an outdated target version to provide compatibility?
It is common practice.
Whether it is "good practice" or not, is highly context dependent. There is a pragmatic trade-off between supporting older applications whose developers don't want (or can't) upgrade, and holding back the development of your application by not making use of new (and presumably beneficial) features.
There is no universal "best" answer.
Is there some form of 'translator' or cross-compiler for Java code?
Effectively, no. For old versions of Java there were "retro-weavers" which allowed you to run "newer" Java on "older" platforms. However, this approach seems to have died out by Java 6.
To answer your first question, it really depends on the standards set by the company/office that you are working for.
From my experience, most of time big companies tries to stay with matured and well established development platforms, they might not give the cutting edge features of the new language, but the companies want the base platforms to be stable and secure first. And if the codebase is large and the project has been in development for a long time, they normally don't bother jumping into the new platform, since that means they might have to invest more resources to rewriting/refactoring a lot of code, which is not always economically lucrative.
I love using those features that you mentioned in my personal projects, but in my office works we are still using JDK6.
As for the second question, I think there are no workable things at this moment that can do the "translation" that you mentioned.
From my experience this isn't a big problem in the industry. Java is used mostly on the server, not so much on the desktop. And to setup a server with the required Java version is not a big deal. For desktop applications I also seen the approach to ship the JRE with the application. It is a little bit ugly to ship a small application (let's say 5 MB) with a 60 MB JRE, but in the "enterprise environment" it doesn't matter and is a practical way to provide the correct JRE. However, I don't like this approach since it leaves open questions, like how to ship security updates to the JRE.
And by the way: Is Java 6 still supported? To use an old JRE is pretty big security issue.
Java 7 has been around for a while now. Now if an application is to be migrated to Java 7 without any changes (code/configuration), are there any inherent advantages or drawbacks? I was curious to know what the problems are faced during such migration.
EDIT:
By Migration I mean the code will remain the same but the runtime will change to Java 7 As I mentioned no code/configuration changes, so thing which I think should impact the application is new compiler/VM level default optimizations. So I was looking for anything which would impact the overall application behavior.
The obvious disadvantage at the moment that I'm finding with my app (which was written in Java 7 to start with) is that most people don't have 7, and it takes a bit of effort to get it. The default Java download page at the time of writing still points to Java 6, not 7, and most of the current Linux distributions just seem to have 6 installed by default as well. Ubuntu 11.10 is the first to even have Java in its repository.
Also on the Ubuntu side of things, one thing I've noted is that even if Java 7 is installed, I haven't found a clean way to check if it's the default yet (and again, chances are it's not.) I'm just using a shell script that parses the output from update-alternatives --query java and launches it appropriately.
It was a conscious decision on my part to go with 7 because there were a number of new features in it that I could take advantage of, and by the time said app actually hits the point where I'd consider it out of alpha / beta I hope Java 7 will have gained more of a foothold then anyway!
The advantages pretty much all centre around using the added features - I've found the try with resources construct has made a lot of my code using IO stuff easier to read (no more nested try / finally's inside try / catches) and I'm using some of the extra APIs like the filewatcher API too. I also rather like the fact JComboBox and the underlying models are now generic which saves a fair bit of casting in Swing apps.
In short though, if you're not actually going to take advantage of any of the Java 7 features and you're just upgrading for the heck of it, there's little motivation to do so until Java 7 at least becomes a bit more established. It's made my code somewhat cleaner and been helpful with some of the additional libraries, but it's also caused a fair few headaches as well.
I would also consider the probability/requirement change of running your new code(java 7) in java 6 or less since some features will not compile like the following:
Strings in switch statements
try-with-resources statements
improved type inference for generic instance creation ("diamond operator")
improved exception handling (multi-catch)
Make sure the version of java used on your considered projects is not likely to be enforced before switching.
The question is really "when", not "if". If you have a pressing need for some of the new Java 7 features (doubtful) then it's obvious.
Otherwise I'd personally wait about year or so to weed out any other possible showstoppers & headaches, before seriously considering a migration production and UAT environments.
Still, you should already have an environment with Java 7 running just to get an idea of what you'll be in for. Java 6 will be retired at some point and you should be well prepared to make the transition.
I think mostly you will be fine with the migration, although you should check with link provided by Oracle about the incompatibilities between Java 1.6 and Java 7
http://www.oracle.com/technetwork/java/javase/compatibility-417013.html
There are few source level incompatibilities like "Improved Exception Handling" in Java 7 which could cause some problems
It is good question and my answer is totally based on experience and new features provided by java 7.
All new features ease the work for developer rather than creating cross compatibility issues.
Only drawback i see in cross compatibilities among different thirds party jars.
You can experience some performance issue between two java versions. And it will depend on area of java code, for details please have a look http://inebium.com/post/java-7-new-release-performance-code
Java came up with "write once run everywhere".
How to do the trick with all the frameworks in the long term?
I wrote an application with JSF and richfaces a few years ago. Browsers have evolved and introduced new features and of course new bugs. Now the application still runs, and sometimes it shows javascript errors from the underlying libraries.
Do we really have to reimplement a finsihed application (no use cases to add) due to technical 'improvements' ?
EDIT: The application I mentioned was just an example. Same things easily happen if vendors change licenses. (Oracle could charge for a vm and open vm is not compatible with you application stack etc.)
Even if we believe "write once, run anywhere", it's not quite the same thing as eternal backward compatibility. Pragmatically, you must expect future versions of frameworks to change some things. Sometimes this will be the removal of what used to be guaranteed behavior (the worst kind of change), other times bugs in your code will go unnoticed until some future version of the library reveals that you were relying on an implementation detail that wasn't guaranteed. More rarely, your old code will reveal a novel bug in the latest version.
In an ideal world, we'd write code which relies only on guaranteed behavior, and guarantees would never be removed, and hence valid code would continue to work forever. Against that, it's hard to prove that your program is totally correct, and the language/framework/library developers make decisions about whether they can add the improvements they want to, while retaining perfect compatibility.
For compatibility to win the argument, the original API has to be strong enough and stable enough to survive without disruptive changes. If it isn't, then either non-compatible changes will be made, or else the API will be abandoned entirely. Either way, your program won't run any more unless you have an old version tucked away somewhere to run it on.
You ask how to do the trick - it requires either really good and somewhat lucky interface design in the first place to allow all the extensions you come up with later, or else a firm commitment and a "business case" (or non-business motive) to support the "old" version indefinitely. For example, Python 3 isn't compatible with Python 2, but Python 2 is still actively supported with updates, so old Python code still runs. C99 removes only a few features of C89, and if all else fails C89 compilers are still actively maintained. Browsers support a thousand and one old versions and non-standard quirks of HTML. I don't know how JSF and richfaces compare to those, or how much they output pages that rely on support for "old" (or quirky) HTML/CSS/Javascript behavior from the client.
So it can happen, at least for a while. But there are IE6 features which are no longer available in any browser that's safe to let out on the web (I guess you could run IE6 in a sandboxed VM, or on a machine you don't care about), so it's a question of what you depended on in the first place. Could it have been predicted that proprietary browser extensions would be dropped like a stone in future versions? Probably, but could those IE6 app-writers have achieved what they wanted to using proper standards available at the time? Not always. Even for those who didn't get involved with IE6, if your app falls into a similar trap, you're out of luck.
I don't suppose anyone can seriously promise "run anywhere, forever". Sooner or later Linux and Windows and MacOS will all be obsolete, new OSes will come out, and no one will bother to write JVMs for them, so none of your Java apps will run any more. (I have an old MS DOS game that I thought was way cool but it won't run under a Windows DOS box. THe company came out with a Windows version but they seriously redesigned the game and, in my humble opinion, destroyed everything that made it fun. Bummer man.)
In the meantime, upward compatibility of new versions is a great thing, but every now and then vendors decide that it's just too much trouble.
It seems that you are speaking not about application but about applet (because you mentioned java script). Moreover this is an applet that calls javascript from page where it is deployed. In this case it is not exactly pure java. It sounds like to call platform dependent command line using Runtime.exec(), then change OS and complain that application does not work.
Or probably I did not understand correctly you use-case?
Programming languages and technologies evolve. Speaking broadly, if a web app is pretty basic, it may be able to take updates without requiring many changes.
Java-based languages seem to update less frequently than languages in the Microsoft stack. JSF 2 has some big changes over previous versions, however, and Richfaces 3.x apps will require migration if you want to use Richfaces 4.x.
As a workaround, you don't always have to upgrade; there are plenty of sites written in older languages (classic ASP for one), deployed and still running happily.
I work on a project that uses multiple open source Java libraries. When upgrades to those libraries come out, we tend to follow a conservative strategy:
if it ain't broke, don't fix it
if it doesn't have new features we want, ignore it
We follow this strategy because we usually don't have time to put in the new library and thoroughly test the overall application. (Like many software development teams we're always behind schedule on features we promised months ago.)
But, I sometimes wonder if this strategy is wise given that some performance improvements and a large number of bug fixes usually come with library upgrades. (i.e. "Who knows, maybe things will work better in a way we don't foresee...")
What criteria do you use when you make these types of decisions in your project?
Important: Avoid Technical Debt.
"If it ain't broke, don't upgrade" is a crazy policy that leads to software so broken that no one can fix it.
Rash, untested changes are a bad idea, but not as bad as accumulating technical debt because it appears cheaper in the short run.
Get a "nightly build" process going so you can continuously test all changes -- yours as well as the packages on which you depend.
Until you have a continuous integration process, you can do quarterly major releases that include infrastructure upgrades.
Avoid Technical Debt.
I've learned enough lessons to do the following:
Check the library's change list. What did they fix? Do I care? If there isn't a change list, then the library isn't used in my project.
What are people posting about on the Library's forum? Are there a rash of posts starting shortly after release pointing out obvious problems?
Along the same vein as number 2, don't upgrade immediately. EVERYONE has a bad release. I don't intend to be the first to get bit with that little bug. (anymore that is). This doesn't mean wait 6 months either. Within the first month of release you should know the downsides.
When I decide to go ahead with an upgrade; test, test test. Here automated testing is extremely important.
EDIT: I wanted to add one more item which is at least as important, and maybe more so than the others.
What breaking changes were introduced in this release? In other words, is the library going off in a different direction? If the library is deprecating or replacing functionality you will want to stay on top of that.
One approach is to bring the open source libraries that you use under your own source code control. Then periodically merge the upstream changes into your next release branch, or sooner if they are security fixes, and run your automated tests.
In other words, use the same criteria to decide whether to use upstream changes as you do for release cycles on code you write in house. Consider the open source developers to be part of your virtual development team. This is really the case anyway, it's just a matter of whether you choose to recognise it as part of your development practices.
While you don't want to upgrade just because there's a new version, there's another consideration, which is availability of the old version. I've run into that problem trying to build open source projects.
I usually assume that ignoring a new version of a library (coz' it doesn't have any interesting features or improvements) is a mistake, because one day you'll find out that this version is necessary for the migration to the next version which you might want to upgrade to.
So my advice is to review carefully what has changed in the new version, and consider whether the changes requires a lot of testing, or little.
If a lot of testing are required, it is best to upgrade to the newer library at the next release (major version) of your software (like when moving from v8.0 to v8.5). When this happens, I guess there are other major modifications as well, so a lot of testing is done.
I prefer not to let the versions lag too far behind on dependant libraries.
Up to a year is ok for most libraries unless security or performance issues are known.
Libraries with known security issues are a must for refreshing.
I periodically download the latest version of each library and run my apps unit tests using them.
If they pass, I use them in our development and integration environments for a while and push to QA when I'm satisfied they don't suck.
The above procedure assumes the API hasn't changed significantly. All bets are off if I need to refactor existing code just to use a newer library version. (e.g. Axis 1x vs. 2x) Then I would need to get management involved to make the decision to allocate resources. Such a change would typically be differed until a major revision of the legacy code is planned.
Some important questions:
How widely used is the library? (If it's widely used, bugs will be found and eliminated more quickly)
How actively developed is it?
Is the documentation very clear?
Have there been major changes, minor ones, or just internal changes?
Does the upgrade break backwards compatibility? (Will you have to change any of your code?)
Unless the upgrade looks bad according to the above criteria, it's better to go with it, and if you have any problems, revert to the old version.
Is it really viable to use GCJ to publish server-side applications? Webapps?
My boss is convinced that compiling our (my) webapp into a binary executable is a brilliant idea. (Then again, he likes nice, small simple things with blinky lights that he can understand.) He instinctively sees no issues with this, while I only see an endless series of problems and degradations. Once I start talking to him about the complexity of our platform, and more in depth specifics of byte code, JVMs, libraries, differences between operating systems, processor architectures, etc...well...his eyes glaze over, he smiles and he has made it clear he thinks I'm being childishly resistive.
Why does he want a single magic executable? He sees a couple of "benefits":
If it is a binary executable, then it is hard to reverse engineer and circumvent any licensing. Management lives in constant fear that this is happening, even though we sell into larger corporates who generally do not do cheat with server software.
There is that vision of downloading this magic executable, running it, and everything works. (No more sending me out to do customer installations, which is not that frequent.)
So, I've done my obligatory 20 minutes of googling, and now I am here.
A bit of background on my application:
What it is made from:
Java 6 (Sun's JVM)
AspectJ 1.6
Tomcat 6
Hibernate 3
Spring 2
another two dozen supporting jar files
What it does
A streaming media CMS
Performance sensitive
Deployed on Linux, Solaris, Windows (and developed on a Mac)
As you can probably gather, I'm highly skeptical of this "compiling Java to native code" thing. It sound like where Mono (VB on Linux) was back in 2000. But am I being overly pessimistic? Is it viable? Should I actually spend the time (days if not weeks) to try this out?
There is one other similar thread (Java Compiler Options to produce .exe files) but it is a bit too simple, the links dated, and not really geared towards a server-side question.
Your informed opinions will be highly cherished, my dear SOpedians! TIA!
I don't know about GCJ, but my company uses Excelsior JET with success. We haven't done it with a webapp (yet) but it should be able to handle anything that the Sun JRE can. In fact JET is a Sun-certified Java implementation.
FWIW: I have never had good luck with GCJ, I have had a lot of problems using it and have had some obscure issues pop up that took forever to diagnose to GCJ rather than me (I am always very very reluctant to blame things on external libraries). I will openly admit this happened several years ago and I have never wanted to go near GCJ again. To give that more substance this was while I was in school and was working on a mostly trivial program so on an "enterprise level" I have had a healthy fear of GCJ.
Excelsior JET is the definitive answer
Having one executable has a few downsides:
You can't patch it as easy (i.e. replace one class file)
I don't think it can be called a webapp -- I assume it won't run in Tomcat.
It is non-standard so that increases your maintenance costs.
It is non-standard so tool support is reduced.
If he wants something simple maybe a war or ear would be better. I can't see any benefit to doing this -- I would think this might be beneficial it it was a standalone application that you distributed so that people can just double-click on it.
I've only used GCJ very briefly, and quickly moved to Sun's JDK. The main problems I saw was that GCJ seems to always lag a little behind the latest version of Sun's JDK and that there were weird mysterious bugs caused by subtle differences with Sun's JDK. In version 1.5 (which is supposd to be compatible with Sun's v1.5), I had problems compiling using generics, and finally gave up and moved to Sun's JDK.
I must say, any difference in performance was negligible (for my purposes, YMMV) and really the solution for installation issues is to create an installer for your app. Reverse engineering a binary isn't really all that harder than reverse engineering bytecode. Use an obfuscator if it is that important.
Overall, I think the compatibility problems involved in using GCJ greatly outweighs any gains (which I think questionable at best) you might possible derive from it. Try compiling parts of your app in gcj and see how it goes though. If it works out fine, otherwise you get something solid to pitch to your boss.
I'll play devils advocate a bit, though I know little about GCJ.
Compiling to native code may give your application a performance boost and use less memory, so if it can be made to work, there are advantages for the business in terms of competition.
Being able to support an application better is also a good for business.
So perhaps it is worth investigating baring in mind that nothing can lose a customer faster than an application that doesn't work.
You need proper project time to try this out and a customer, that knows what they are getting into, that is willing to give it whirl (harder to find).
I don't think that a large application like yours will compile to machine code. Remember that java is not only java syntax (might compile to machine code) but also a virtual machine which is more like an application / process environment. I would suggest making an uberjar or like that instead.
Perhaps your boss just needs a demo as to how easy it is to distribute and deploy a war file for your customers on their own app servers. Every file is "binary", so you might be too-literal in thinking he means an executable on the command-line.