Are there any known security issues with compiling against an older JDK? For instance lets say Oracle decides to change something in one of their implementations that was to close a security vulnerability. If we compile against the older JDK would we still be vulnerable?
EDIT
We are running against JDK 6 and we compile against Java 5, which is the crux of the issue I was attempting to get at for any one else whom sees this question. For the sake of completeness lets say that in the ant build we target 1.5
EDIT 2
Additionally there is the issue of calls in the application that potentially have private APIs/implementations that are not directly accessed.
Aside from some very hypothetical niche situation that hasn't ever happened yet, the only thing that matters is the version with which the application is executed.
I don't think there are any known security issues that have been "fixed" with #deprecated, because that wouldn't really be appropriate.
There are two issues at play here:
1) You can have your Java compiler produce binaries that are binary compatible with older versions. That affects the language features available to you.
2) You can compile against the Java system libraries of an older version, and that will affect what methods/classes are available, as they are always adding new ones.
But neither of these affects the security of your application. What matters is the runtime version with which the application is executed.
Observe that security problems are fixed between updates, not the major versions, which introduce changes in the language itself. For example, Java 6 is currently at update 21. Java 6 update 19 fixed stuff that was vulnerable in Java 6 update 18.
When Java 6 update 19 was released, updates were released for Java 1.5 and Java 1.4, to fix the same issues in Java 1.5 (update 24) and Java 1.4 (update 26). See the security baseline table here: http://www.oracle.com/technetwork/java/javase/6u19-141078.html
If you compile against JDK 1.5:
Users that are using JRE 1.5 will be vulnerable
Users that are using JRE 1.6 will not be vulnerable
The application will run using the libraries of the users's runtime. Since the vulnerabilities are fixed in Oracle's library, which is now being called by your application, the security vulnerability will be alleviated.
However, since you compile against 1.5, your users will be able to use 1.5. Do anything you can to avoid the vulnerability; if you can't avoid it, detect the JRE version at startup and issue an alert if apporpriate.
If Oracle changes an API (not an implementation) to promote security, they will probably add an #Deprecated annotation but preserve backward compatibility for some time. The annotation will trigger a warning in a newer compiler, but not in yours, and not in the compiled program. (Unless Oracle decides to throw an exception or log a message from the deprecated method.)
I would say that those unfixed vulnerabilities are still there, and you and your app are still at risk.
It'd be the same issue as running with an old, unpatched OS or browser.
It's a good incentive to migrate up to newer JVMs.
Related
I have a program for work that I'm told will only use Java version 8 update 192 to run correctly. When I downloaded eclipse, it's suggesting that I use JRE 17.0.2 but I recalled my coworker saying I need Java 8 update 192 otherwise it won't work. Does the JRE version matter? Is it irrelevant?
Perhaps I need to download JRE 8.192? I'm not sure. Any help would be appreciated.
I have a program for work that I'm told will only use Java version 8 update 192 to run correctly.
I would doubt the accuracy of that statement. I would say that someone is making a statement without evidence ... if that is what they actually said.
Maybe a more accurate statement is that the program is only known to run on that particular version ...
Anyway, it will probably run on a later version of Java 8, or Java 11. Java 17 is less certain because of the issue of package sealing / blocking of access to internal packages that occurred in Java 16. (Some of the sealing / blocking started in Java 9 ... but there are easy workarounds ...)
Q: Do you need a JRE?
A: No. A JDK will work just as well. (A JDK distro includes a JRE.) But unless there are strong counter-indications, you need the latest version of Java 8, 11 or 17. Java 8 u192 is years out of date.
The only way to be sure that the application will work on a particular version of Java is to try it. In general, there are no shortcuts.
Java 8 is still available, as the first Long-Term Support (LTS) version. The current release is Update 331. I would suggest starting with the latest update of Java 8.
Be aware that Java 8 is not receiving regular updates for the public except for critical security patches. You may want to consider paying for a support contract from any number of vendors such as Azul Systems or Oracle to get support including possible additional updates releases through the rest of this decade.
Generally Java apps will run on later versions of Java without any modifications needed. The Java team at Oracle and the OpenJDK community place a very high priority on preserving that compatibility.
However, there are exceptions to the compatibility policy. In particular: Java 9 introduced the Java Platform Module System which caused some problems in some apps. And in later versions of Java some libraries that were previously bundled are now removed. Some of those removed libraries were transferred to the Jakarta EE project at the Eclipse Foundation. Some were abandoned for lack of interest such as CORBA.
Some few parts of Java that were for years marked as “deprecated for eventual removal” have now been removed.
If you consider moving beyond Java 8, I suggest your first step be sitting down to read through the Release Notes for every release of Java. They are quite well-written. They should alert you to any issues that may affect your app.
FYI, Java 17 is the latest LTS version. Java 18 is current.
As in the other answers, an application built for Java 8 will probably work fine in Java 17, with some caveats, but if you absolutely need the final product to run under Java 8, go get a real Java 8 runtime and set it up in your IDE. Building a Java application for any specific Java version is best done by having an actual copy of that runtime present, preferably a JDK. By having an exact version of its standard library to compile against, you can avoid accidentally referring to packages, classes, and methods added to, or removed from, later versions. You can get an OpenJDK build of Java 8 from https://adoptium.net/?variant=openjdk8 . Be sure to ask your co-worker why they're mentioning an outdated patch version.
Additionally, keep in mind that Eclipse is itself a large Java application. Running it requires Java, and a growing number of downloads include a Java runtime for that simple reason, even the ones that do not include Java development tools. You don't have to compile your code against that version of Java, though--you probably don't even want to since JDK downloads will include JavaDoc for the standard library, among other useful extras.
We have been following the official Java migration guide to upgrade our application from Java 6 to Java 8. Unfortunately we haven't set source and target version to 1.8 to prevent the usage of new language features.
So currently we are compiling and executing our application with JDK 1.8 / JRE 1.8 but set source and target level to 1.6.
Nevertheless, we now even want to level up the source and target level for our applications to 1.8.
Does setting those properties only changes the allowed features for the compilation and the binary format of the classes or does the configuration changes the semantics of the application? We expect that there shouldn't be any known issues or incompatibility when updating the source and target version to a higher version, when staying on the same JRE for execution and JDK for compilation.
Does setting those properties only changes the allowed features for the compilation and the binary format of the classes or does the configuration changes the semantics of the application?
It can actually change the semantics of the Java language. For example, the meaning of #Overrides changed between Java 5 and Java 6. (I can't recall any changes like that between Java 6 and Java 8, but ....)
And of course:
There will be library bug fixes.
There will be cases where methods or classes are re-implemented (e.g. Arrays.sort and HashMap) with differences in unspecified aspects of library behavior.
Changes to the JIT compiler can lead to native code being optimized differently which can lead to timing or memory model-related regressions in (your) buggy multi-threaded code.
In short, even though upgrading from one version to the next ... or just changing the --source or --target is usually innocuous, it can sometimes lead to problems that need to be fixed.
So ... test everything ... thoroughly. Don't assume that it will all just work when you roll our the newer version.
Of course, it is advisable to read the lists of bug fixes and incompatibilities in the respective release notes. But be aware that the lists may be incomplete, or that you won't realize that some fix impacts your code. (Who knows / remembers every implementation detail of an large application written many years go?) And be aware that the fixed bug lists in a new major release are incremental from a previous patch release.
The counterpoint is that, you can't just defer upgrading because. The longer you put it off, the harder it becomes and the larger your codebase's technical debt becomes. And you may find yourself having to do the upgrade in a panic; e.g. due to an unpatched security problem, an OS support issue, and so on.
According to Compatibility Guidelines at the source level, JDK 8 is strongly compatible with previous versions however there're corner cases (explained in the guide).
What you refer to as "changes to the semantics" is a result of not only behavioural incompatibilities, including changes in API implementation (for example this bug which is fixed in 8), but also the platform itself.
Therefore your code compiles and runs, but it might have bugs.
Bottom line, only your test cases can guarantee the smooth transition.
Update
Changing source compatibility to 8 does not break compile of existing source which is in lower level, e.g. 6.
Changing binary compatibility changes the version of the generated bytecode, i.e. compiled .class files, and obviously you compatible runtime environment.
JRE is backward compatible when deals with bytecode. You can run the new bytecode (e.g. your compiled source) along with old bytecode (e.g. your dependencies).
You might experience some semantic changes due to different platform and API implementations, including runtime libraries.
Some of the semantic changes are not easy to catch even with test cases (my personal was experience with Java Crypto API and SSL).
A slightly related to the topic of target and source. This depends on if your application is library which can be included in other projects. For example prior to AS3 you could not include libaries which where compiled with target and source > 1.7 although the code semantics were exactly the same. Even if the library did not include any Java 8 features e.g. streams.
So that might be a "check mark".
Our Java Applet is built using JDK 7u7.
We have a client who is worried that this exposes them to security flaws that were patched between 7u7 and the current Java 7 release (7u72). (They're not worried about any specific known issues, just "concerned".)
I believe the answer is that because the package is dependent on calls to the JRE libraries, it will call the (fixed) 7u72 libraries, and therefore the fact that it was developed against 7u7 will not be an issue.
Is this correct? A link to authoritative statements on this point would be much appreciated.
It is correct. Output of compilation is defined in the java VM specification in class file format, which has not changed between java update releases, it doesn't matter if it's compiled in 7u7 or 7u72.*
You can see all the java virtual machine specifications since java 5 on this page. There are no other changes to the specification, so it has only changed between major releases.
*on further thought, this assumption is true only if there hasn't ever been security-related bytecode generation bugs in JDKs. I've never heard of one, and certainly between versions 7u7 and 7u72 there isn't any. I guess it is possible in theory, but at least for the cases you specified there aren't such security issues.
in detail:
if we use public API for example, write java program for example , in JDK 1.4, if should run correctly in all version above it. in all update version in 1.4, in 1.5, 1.6 and 1.7?
Also , what is the combability rule between different updater versions , for example 1.6.22 and 1.6.23 what can not be changed, what can be changed?
of course, public API definition can not be changed, how about others? javadoc? internal API definition, implementation?
It will be great if someone can point a concrete official document on this topic. thanks,
there is one example in java document bug, that they intended not to change between updater version. see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6475885
this should be one of its big picture, but we better to have a complete description on this.
need to know the complete story so that we feel safe to upgrade to bigger version.
The general rule is that any code that is written and compiled against the APIs of Java X should run on Java Y where Y >= X.
There are occasional exceptions to this; e.g. where the application's behaviour depends on some undocumented behaviour (typically a bug) in Java X that was corrected in a later version.
AFAIK, there is no single document that lists these incompatibilities. The release notes for all of the Java major releases include a list of changes that could result in breakage of older code.
Having said that, the prudent approach is make sure that you thoroughly test / retest your software when you upgrade to a more recent Java release. And if your software is shipped to customers / clients, let them know if / when it is safe for them to upgrade, and (if necessary) provide them with fixes for any problems that your testing has uncovered.
need to know the complete story so that we feel safe to upgrade to bigger version.
Feeling safe is beside the point. Thoroughly test your application on the later version. That is the only practical solution. And that would be the case even if each and every incompatibility was exhaustively documented.
Think about it. How can you know for sure that your application won't somehow be affected by change XYZ? Or that some 3rd-party library that you use won't be affected? Answer: you can't.
No manner of complaining here that you think that Oracle should handle this issue differently is going to make any difference. Not that I think that they could handle this better without changing their business model. How much would you be prepared to pay for a Java platform that guaranteed there were no version compatibility issues?
This is not a full answer but I will add that will-it-run and will-it-compile are two different things. Keywords introduced in 1.5 will prevent some 1.4 code from compiling but the byte code will run just fine.
Almost anything can be changed between versions there are no set rules for such things. Use the release notes to publish changes or review them between versions such as:
http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html
Usually only bug fixes are the cause of minor versions (like you detail 1.6.22 - 1.6.23), or simple enhancements which are only ever good things. When the major version numbers change then you can expect more major changes but you still "hope" for reverse compatibility.
I don't think JDK ever changes an API that breaks backward comparability (except unintentionally).
They introduced #deprecated tag in the very beginning, probably thinking that they may need to do some API cleanup in future. But that never happens. No #deprecated API has ever been removed, or behavior changed.
if we use public API for example, write java program for example , in JDK 1.4, if should run correctly in all version above it. in all update version in 1.4, in 1.5, 1.6 and 1.7?
See this table, that shows breaking changes in public jdk APIs
See these official documents about versions compatibility:
Java SE 7 and JDK 7 Compatibility
Java SE 6 compatibility with J2SE 5.0
Incompatibilities in J2SE 5.0 (since 1.4.2)
Java SE 1.4.2 Compatibility with Previous Releases
Is there some statistic on how widely people use various JRE's? I'm asking, because I created a program (using JDK 1.6), and found that it would not work on JRE 1.5 and older. So, do I need to bother making it compatible, or maybe the percent of JRE 1.5 out there is too small?
Here is some stats:
http://www.statowl.com/java.php
Don't really know how it's calculated... I think come from users browser, but don't know which websites.
You need to have your JDK emit bytecode for older JVMs with the -target SDK_VERSION argument to javac. Bytecode from one version of the JVM is not compatible with an older release of the JVM.
Thanks to comment
The above only works if you are not using functionality that older JVMs don't have, for example, if you took advantage of the Java Desktop API, which was introduced in 1.6, you wouldn't be able to target an older JVM anyway.
I won't throw statistics your way, I don't really know what your application is/does/who it's intended for, but there are companies and people who still use older JDKs - perhaps due to heavy investment in some specific release of the JVM and it would require significant time and testing to ensure that moving to a newer version does not break their existing software/code, or perhaps some software strictly mandates it. I worked with software from a company (which shall remain unnamed) that ONLY wanted a specific patch revision of an older JVM - their software refused to work on anything newer.
Um yes plenty of enterprises use earlier versions of Java. You simply need to decide what your lowest level target JVM is. Don't forget you can use the -source & -target parameters to specify the type of source code and byte code compatibility with earlier versions.
I don't know of any statistics, but for what is worth I am certain people use Java 1.5. If your app is geared toward general public, I don't think you need to bother, but in specialized environments it might be.
If your application will be for consumers, you will probably be fine relying on 1.6.
Most places that are still running 1.5 are for business applications that have not been updated.
If you're not using any Java 1.6 specific features, you can pass a command line argument to javac to target the 1.5 framework. The argument to add is -target 1.5. Obviously this wouldn't work if you're using any new features shipped with 1.6.