import sun.net.www.protocol.jar.Handler causes the following warning:
sun.net.www.protocol.jar.Handler is
Sun proprietary API and may be removed
in a future release
There is no replacement. You have these options:
Use it and fix the problem if the API is ever removed (which won't happen in the next two years, at least). The most dangerous option but the most simple to implement.
Copy the code into a new class/package in your project to make sure it doesn't go away. Most safe, pretty easy to implement but you don't get bug fixes and classes in the runtime will still use the old handler.
Write your own extension of URLStreamHandler. Most work, least return of investment, high likelihood of bugs, most dangerous.
Rationale: This is a warning. Warning means: You may run into trouble if you do this. Use your common sense to decide.
Related
I don't know how to fix this error can you please help me?
Execution failed for task ':app:processDebugMainManifest'.
Unable to make field private final java.lang.String java.io.File.path accessible: module java.base does not "opens java.io" to unnamed module #203e7cb0
I am very grateful for every answer.
Explanation: Your tooling (The code that powers the processDebugMainManifest task, which I think is the Android Build System) is trying to do a task in java, but this task is simply not available in public APIs. Instead of accepting that it is impossible to write an Android Build system in java in the way the android team wanted, the devs of android instead realised that JVMs can do it, it's just that there is no public accesspoint to ask it to do it. Thus, they decided to use the not-intended-for-public-consumption part, given that without doing this they can't do the job at all, and have accepted the maintenance burden.
Unfortunately, Team OpenJDK is aggressively locking this stuff down, even though usually there is no ready alternative (as in, the right order is obviously to first make an inventory of commonly used private APIs, then make suitable alternatives for the top 95% of usage, and then proceed with lockdown, though not in such a heavyhanded fashion as they have chosen to do - team OpenJDK hasn't done this)1.
That's what this warning means: The java release you use is no longer 'allowing' it. This java release has broken processDebugMainManifest for a dubious reason. Likely whatever pDMM is trying to do is now completely impossible in java releases that locked this down and thus...
Solution:
Downgrade your java.
Download AdoptOpenJDK's OpenJDK8 which is free and open source.
In particular when doing android dev this is generally a good idea. Android has never worked well with newer javas; neither the features introduced in the language, nor the additions to the core libs (as android has its own implementation of them). The existence of this courtcase probably isn't helping things along.
[1] I have oversimplified a tad; for example, there are a few methods in sun.misc.Unsafe which OpenJDK openly states are sometimes neccessary and they are more or less committed to keeping Unsafe available until they've found adequate alternatives for all such uses (if only they had that attitude for a few more commonly used internal bits, there wouldn't be such a gulf between the community and the openjdk team). Also, there is common 'internal API' usage which is indeed inappropriate, such as the widespread use of sun.misc.BASE64Encoder which no library/tool/app ever should have used, and for which alternatives have always been available, and these days, alternatives are baked into the JDK itself: Team OpenJDK's decision to effectively eliminate both direct access to BASE64Encoder as well as shutting down all attempts to work around the lack of direct access are therefore probably justified. It's shades of gray: Whenever private API use occurs, part of the blame lies with the OpenJDK for not having an alternative, and part of the blame lies with the library/tool/app for envisioning the way it works in a way that can't be done (easily) without relying on internals that weren't designed for public use like this. My impression is that the core OpenJDK contributors are wildly misjudging themselves on this divide and basically placing virtually all blame not on them but on the library builders, and aren't giving sensible solutions other than 'pull your entire tool/library/app from existence, you should never have written it'. Thus, I'm faring on statistics here, but it is quite likely the explanation of whatever's going on here: The OpenJDK is locking down the ability to do this stuff without having a reasonable alternative, therefore processDebugMainManifest, even the most recent version, would still cause this error and they can't fix this error without rewriting a ton of code and completely changing how it works for the users of the Android Build infrastructure.
Some insights (including that vibe that OpenJDK core contributors seem to feel the blame lies almost entirely with apps/libraries/tools) is on display on this Inside Java podcast with Alan Bateman.
In Java, a compiler plugin is made by subclassing com.sun.source.util.Plugin (in Java 11). Java compiler plugins use classes that inherit from Tree,
https://docs.oracle.com/en/java/javase/11/docs/api/jdk.compiler/com/sun/source/tree/Tree.html
These classes seem not to allow changes in the AST. However, some plugins, as those described in
https://bkushigian.github.io/2018/06/03/optimizing-javac-plugin.html
and
https://www.baeldung.com/java-build-compiler-plugin
do change the AST. The question is: is that a hack?
Not a hack. The examples are old/misleading (anything using Method.setAccessible(true) is always a hack) but the com.sun.tools.javac.tree.TreeScanner visitor and TreeMaker factory are as official as the javac API is ever going to get.
From their javadoc:
This is NOT part of any supported API. If you write code that depends
on this, you do so at your own risk. This code and its internal
interfaces are subject to change or deletion without notice.
This is their freedom to innovate without the compiler becoming a backwards-compatible mess like the main JLS/JDK sometimes is. You can understand why they would need this statement and I do not consider it a hack but it a warning about the amount of future maintenance you may need over time. IMHO sub-classing TreeScanner is quite accommodating of future language changes and I would not expect fundamental incompatibilities as new language features are rolled out.
While studying the standard Java library and its classes, i couldn't help noticing that some of those classes have methods that, in my opinion, have next to no relevance to those classes' cause.
The methods i'm talking about are, for example, Integer#getInteger, which retrieves a value of some "system property", or System#arraycopy, whose purpose is well-defined by its name.
Still, both of these methods seem kinda out of place, especially the first one, which for some reason binds working with system resources to a primitive type wrapper class.
From my current point of view, such method placement policy looks like a violation of a fundamental OOP design principle: that each class must be dedicated to solving its particular set of problems and not turn itself into a Swiss army knife.
But since i don't think that Java designers are idiots, i assume that there's some logic behind a decision to place those methods right where they are. So i'd be grateful if someone could explain what that logic really is.
Thanks!
Update
A few people have hinted at the fact that Java does have its illogical things that are simply remnants of a turbulent past. I reformulate my question then: why is Java so unwilling to mark its architectural flaws as deprecated, since it's not like that the existing deprecated features are likely to be discontinued in any observable future, and making things deprecated really helps refraining from using them in newly created code?
This is a good thing to wonder about. I know about more recent features (such as generics, lambda's etc) there are several blogs and posts on mailing lists that explain the choices made by the library makers. These are very interesting to read.
In your case I expect the answer isn't too exiting. The reason they were made is hard to tell. But both classes exist since JDK1.0. In those days the quality of programming in general (and also Java and OO in particular) was perhaps lower (meaning there were fewer common practices, library makers had to invent many paradigms themselves). Also there were other constraints in those times, such as Object creation being expensive.
Many of those awkwardly designed methods and classes now have a better alternative. (See Date and the package java.time)
The arraycopy you would expect to be added to the Arrays class, but unfortunately it is not there.
Ideally the original method would be deprecated for a while and then removed. Many libraries follow this strategy. Java however is very conservative about this and only deprecates things that really should not be used (such as Thread.stop(). I don't think a method has ever been removed in Java due to deprecation. This means it is fairly easy to upgrade your software to a newer version of Java, but it comes at the cost of leaving some clutter in the libraries.
The fact that java is so conservative about keeping the new JDK/JRE versions compatible with older source code and binaries is loved and hated. For your hobby project, or a small actively developed project upgrading to a new JVM that removes deprecated functions after a few years is not too difficult. But don't forget that many projects are not actively developed or the developers have a hard time making changes securely, for instance because they lack a proper regression test. In these projects changes in APIs cost a lot of time to comply to, and run the risk of introducing bugs.
Also libraries often try to support older versions of Java as well as newer version, they will have a problem doing so when methods have been deleted.
The Integer-example is probably just a design decision. If you want to implicitly interpret a property as Integer use java.lang.Integer. Otherwise you would have to provide a getter method for each java.lang-Type. Something like:
System.getPropertyAsBoolean(String)
System.getPropertyAsByte(String)
System.getPropertyAsInteger(String)
...
And for each data type, you'd require one additional method for the default:
- System.getPropertyAsBoolean(String, boolean)
- System.getPropertyAsByte(String, byte)
...
Since java.lang-Types already have some cast abilities (Integer.valueOf(String)), I am not too surprised to find a getProperty method here. Convenience in trade for breaking principles a tiny bit.
For the System.arraycopy, I guess it is an operation that depends on the operating system. You probably copy memory from one location to another in a very efficient way. If I would want to copy an array like that, I'd look for it in java.lang.System
"I assume that there's some logic behind a decision to place those
methods right where they are."
While that is often true, I have found that when somethings off, this assumption is typically where you are mislead.
A language is in constant development, from the day someone proposes a new language to the day it is antiquated. In between those extremes are some phases that the language, go through. Especially if someone is spending money on it and wants people to use it, a very peculiar phase often occurs, just before or after the first release:
The "we need this to work yesterday" phase.
This is where stuff like this happens, you have an almost complete language, but the programmers need to do something to to show what the language can do, or a specific application needs a feature that was not designed into the language.
So where do we add this feature?
- well, where it makes most sense to that particular programmer who's task it is to "make it work yesterday".
The logic may be that, this is where the function makes the most sense, since it doesn't belong anywhere else, and it doesn't deserve a class of its own. It could also be something like: so far, we have never done an array copy, without using system.. lets put arraycopy in there, and save everyone an extra include..
in the next generation of the language, people will not move the feature, since some experienced programmers will complain. So the feature may be duplicated, and found in a place where it makes more sense.
much later, it will be marked as deprecated, and deleted, if anyone cares to clean it up..
I am currently upgrading from JAVA 1.4 to JAVA 6 SE. Some of the methods and classes have either been deprecated or there are a lot of warnings due to inefficient practices. I want to know if it is possible for me to upgrade without making any changes to my code and after the changes remote debug to fix the errors. If there's a simpler or more efficient way of doing this please share.
The usual approach is:
Run your code through the new compiler
Fix any compile errors (might happpen in some rare cases, like when you used the word enum as identifier, which is a keyword for Java 1.5 and greater)
Do a full QA cycle to verify that your application still works properly
Besides that, you should consider upgrading to Java 7 - Java 6 is also already in its end-of-life phase.
I want to know if it is possible for me to upgrade without making any changes to my code and after the changes remote debug to fix the errors.
We can't give you a definitive yes or no to that.
First, it should be noted that most of the deprecations and warnings can be ignored to start with. (Some are telling you about things that should be fixed soon, but the most egregious examples of bad / dangerous APIs were deprecated long before Java 1.4)
So one reason we can't give you a definitive answer is that we don't know what warnings you are seeing (duh!).
The other reason is that we don't know how good / extensive your test suite is. If you have a good test suite, the chances are good that any problems will be picked up. If not, or if you are relying on manual testing, then your chances of finding any problems cause by the upgrade are greatly reduced.
The other thing to note is that the documentation for each major Java release includes a section on Incompatibilities between the new release and the previous one. It is a good idea to at least skim these documents to see if any of the issues highlighted are likely to impact on your application.
Finally, most people find that upgrading doesn't result in a large swath of problems. There are exceptions of course. And if you are in the habit of depending on implementation specific behaviour rather than what the javadocs say, THAT can lead to pain.
Basically, you can run your Java 1.4 code on a Java 6 virtual machine without modifications. New API's might have been introduced, effectively deprecating old ones. Usually, the Javadoc of the deprecated API should give you a pointer what you should use instead.
Do any problems arise because of using deprecated functions in Java?? If so, why do they keep this function?? Is it a bad habit if you use a deprecated method in Java like
java.sql.Date.getMonth or getYear or getDate???
Some potential problems are:
Methods may cease to exist (this has never been the case in practice, but by the official definition, deprecated methods may be eliminated from future Java)
Serious programming errors may occur due to fatal flaws in deprecated methods (e.g. System.runFinalizersOnExit and its evil twin Runtime.runFinalizersOnExit)
Data corruption can occur due to inherently unsafe deprecated methods (e.g. Thread.stop)
References
java.sun.com Glossary
deprecation: Refers to a class, interface, constructor, method or field that is no longer recommended, and may cease to exist in a future version.
Language guide/How and When to Deprecate APIs
Annotation Type Deprecated API
Related questions
Is it wrong to use Deprecated methods or classes in Java?
Difference between a Deprecated and Legacy API?
No methods have actually been removed yet so existing code will keep running. Sun has been very focused on backward compatability.
The primary benefit is to move away from code that for some reason has been found to work suboptimallly, and usually there is a replacement elsewhere in the runtime library. Hence it is a bad habit to use them, and you should take heed and use the recommended replacements whenever the compiler flags a deprecation. It is generally a good idea to aim to eliminate compiler warnings.
You can see a list of what is deprecated in the Javadocs. The Java 5 list is at http://download.oracle.com/javase/1.5.0/docs/api/deprecated-list.html
Deprecated methods are kept so that code written for a previous version of Java still functions. If they just removed the code then previously functioning code would stop working when you updated Java to a new release.
Using deprecated functions will not cause you any problems beyond that which caused the method to be deprecated. However, it is best to find out what has replaced the deprecated method. The deprecated functionality will have been replaced with new functionality possibly found in a new class. Much of the deprecated Date functionality has been moved to Calendar. Check the Javadoc for the to see the recommended replacement.
The code may break in the future...
deprecated functions are a warning that this function will go away.
Look for alternative ways to fix the problem now, or you will
have the code break in the future.
A deprecated class or method might get removed in a future version. Sun had the habit of deprecating stuff and never actually removing it which in my opinion is not so good because it makes it seem Ok to use deprecated methods. Still you should not use deprecated methods where possible (and it should always be possible). This goes especially for external libraries which imho generally are not as afraid as Sun to remove deprecated code.
As others have pointed out, Sun has never removed any deprecated methods from the JDK, but the same is not true with deprecated methods in third-party libraries. Those do disappear sometimes (the Lucene project for example has a rather "fluid" API here, doing major cleanups with major versionups).
Even in the JDK, the method being deprecated means that "there is a better way to do this now", and you should probably update your code to use the new version.
It is very rare that the deprecated method does not work correctly for what it was originally intended to do, but the replacement will usually work more reliable, or in more circumstances, or in a more general way. Good examples here are the Date functions that you mention (deprecated because they do not work well with different locales/calendars), or String-to-byte conversions that only work with 7-bit-ASCII. These caveats/restrictions cannot be fixed without a new interface, or because someone may depend on the "broken" implementation, so instead of updating the method, they deprecate it and provide an alternative one.