How to distribute AWTUtilities - java

I recently read the blog posts on Pushing Pixels that describe how to achieve native transparency and translucency with pure Java. The needed classes reside on com.sun.awt namely com.sun.awt.AWTUtilities.
I was wondering how i could include the needed classes (not just this one) into my distro since the classes are available only when you have a jdk installed and you start the jvm through there. So the users of my program will not have the needed classes to run my program.
Any ideas?

AWTUtilities, as the package implies is an implementation package and is subject to change. I don't think it is a good idea to distribute the class from both technical and legal viewpoints.
Technically, com.sun.awt.AWTUtlities is bound to have possibly unknown dependencies on other classes and internal implementation details, specific to Java 6 u10 and above (the release in which it appeared). This unknown dependency angle is bound to hold water, since painting and graphics will require changes in some of the native implementations as well.
Secondly, this is bound to change in Java 7, since the only release Sun hasn't made a release of java.awt.AWTUtilities with support for transparency, is because they do not make changes to public APIs except in major releases.
IANAL, but I do not think it is wise to engage in the act of redistributing software without having run past a lawyer. Besides, customers do not like the idea of having an unsupported deployment of any software in their systems.
Update
All Sun JREs (not just JDKs) from 6u10 onwards come with com.sun.awt.AWTUtilities, so the simplest course of action would be to get your users to have Java 6u10 or later on their systems, and for your application to handle any resulting exception gracefully.

Related

Why aren't Java package vulnerabilities fixable with a single patch?

I have zero experience with Java, but when trying to understand a certain "apocalyptic" vulnerability, I ended up with a fundamental question about imports in Java, so please bear with me.
My question is, as given in the title, why a Java package can not be updated with a single central patch.
For comparison, two hypothetical diametric cases that I think I understand reasonably well:
If, say, a python library had some vulnerability, then it should suffice (on well-maintained systems that use centralized libraries located on PYTHONPATH) to update that single library and any code that imports it should, in general, be fixed.
On the other hand, if a C library had a vulnerability, then it would be necessary to replace every single binary whose source includes the vulnerable library with a patched binary.
Now, as far as I could tell, Java is actually closer to the former category of languages, where external imports are not included in compiled sources.
If this is the case, then why can't a single patch be applied to fix an entire system (au contraire, our IT department forwarded a gigantic list of software for us to check individually)? Is it because of multiple decentralized copies of identical libraries being installed, or is there some other reason? Or am I misunderstanding the issue?
Java applications themselves are separate processes. In principle, all these processes can use different VM's. This is often the case for larger applications, which are tested against a specific VM. In principle, Java runtimes (J2SE implementations) should remain as compatible as possible with each other, but it is certainly possible for developers or libraries to muck this up, e.g. by using "Sun" inner classes or by assuming things not specified for the API calls. Personally hate these kind of J2SE inclusions; I'd rather have applications that are created to remain compatible.
Smaller applications usually just run on one of the installed JRE's. However, they usually still need additional libraries or components - say, for instance, Log4J from Apache. These are often offered as separate .jar files (or "artifacts" in Maven speak). These libraries may also get updates; there is however not a common way of updating these on most systems; there is no single "application" set of shared libraries although it is certainly possible to create one. On Linux for instance there may be a set of libraries in /usr/share/java (by version, with generic names pointing to the latest one).
Many web applications - I those running on a specific application server such as Tomcat, Glassfish etc. do share a common "classpath", where application specific .jar files are put in specific folder. In that case an update of a library in the shared folder will affect all applications.
Java has had a framework for specific class-loaders, and in principle any framework can define their own set, so where the libraries are stored can depend on the framework. Java is very flexible and doesn't really have one single way of handling applications.
All this has previous little to do with import statements. These are just use as a shorthand notation, basically. You might as well use java.util.List as import java.util.List followed by List further in the code. Class files contain references to other classes (etc.), and those are resolved (found and loaded) at runtime; see the description from Oracle here.

I don't know how to fix this error in the question

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.

What are "programs" in a VST instrument?

I have recently started using jvstwrapper and also the juce framework. It appears that the VST SDK has some concept of different "programs" for your instrument. For example both jvstwrapper and juce have classes which you inherit from in order to create your instrument. These classes require a number of methods to be implemented. In both cases, (and detailed in the VST SDK), you must implement methods "setProgram", "getProgramName", "setProgramName", "getNumPrograms" etc. I know that each program appears to hold a bunch of settings for the instrument. But in what cases are they actually used? Plus how many are there supposed to be?
A VST program is similar to a hardware ROM preset, or a MIDI program change message. The hardware analogy makes more sense if you are familiar with older synthesizers, which often shipped factory presets that could be "dialed up" and then tweaked accordingly. Some hosts will present the list of programs as a dropdown menu so that users can quickly browse factory presets.
Regarding the number of possible programs a plugin can have, the VST SDK uses VstInt32 (a 32-bit integer) for the program index. So a plugin could theoretically have up to 2147483647 possible programs. In practice, most hosts limit this to 127 (to be compatible with MIDI program change messages), so it is unwise to expose more than 127 programs or else the host might have problems with your plugin.
IMHO the concept of VST programs is a bit dated and obsolete. It makes far more sense for your plugin to support the FXP/FXB features of the VST SDK so that the user can import/export patches from/to the hard disk. As you might expect, Juce of course has hooks for loading and saving VST preset files.
Many modern plugins don't support VST programs, and it's totally acceptable for your plugin to return 0 in the getNumPrograms() call.

Mixing Java 1.4 and 1.6 bytecode in a class hierarchy

The question first, the story will follow:
Is it safe to mix different bytecode version in a class hierarchy? What are the risks?
For a case, Class C extends B, Class B extends Class A. Class A implements Interface I.
My question would involve following example scenarios:
Class A compiled to Java 1.6 bytecode, and have 1.6 features such as generics, etc. The heirs, which are B and C was compiled to 1.4 bytecode.
Interface I compiled to 1.6, while the implementor compiled to 1.4.
Other exotic inheritance scenario involving different version of bytecode.
I have tried as many scenarios I could imagine and it seems to run just fine. However I still feel the urge to ask here as I only know Java at the surface; i know how to code and tweak Java but don't really know what happen under the hood.
Now for those minds who can't help themselves to ask "why would you need to do that???".
I'm in a project to assess the migration of legacy Java 1.4 Swing app, connected to EJB 2 via RMI, to Java 1.6 Swing connected to newer version of App Server running on top of 1.6 also. The J2EE platform will still be 1.4 (EJB 2).
The migration will not be "recompile everything to 1.6", but it will be "code and compile new features to 1.6".
The way they do things is like this:
They only have one path in the CVS, everyone commits there. No tags/branches whatsoever to get the production code.
Whenever a new feature need to be added, they get the JARs from production server, explode them, replace or add new classes as needed, repackage the jars, put them back to server.
Therefore, if they will use Java 6 to compile and using the above method for deployment, there will be a lot of exotic mixes of 1.4 and 1.6 bytecodes.
The JVM byte code is not siginificantly different between Java 1.0 and Java 6. In Java 7 they add one new instruction. Woohoo.
There are so little changes in how the byte code works that
The JVM doesn't support nested classes accessing private members of outer classes, this works through generated code.
The JVM doesn't support runtime checks for generics e.g you cannot new T() where T is a generic.
Basically, they make the JVM smarter and faster but until recently changing the model of how the byte code works has been avoided at all costs.
You can compile with Java 6 but target 1.4 with a compiler setting. We did this for a migration project once. If/when 1.4 disappears, you then change your compiler settings again and target 1.6.
Keeping the target version explicit also means that you can upgrade your SDK without fear of your JAR files becoming unusable to an older JVM.
I am maintaining an environment with mix of 1.4 (old library jars) and 1.5 (my fixes and stuff) classes on Tomcat using Sun JVM 1.5 and it runs fine.
However, for RMI you may be in trouble if client and server has different class version because the server might check the class version (I ran into this problem).
The best way to find out is to do a proof of concept type of project on small scale.
A friendly reminder though, you are digging a pretty big hole for yourself here :-)
These links seem relevant. They document the few edge cases that could break compatibility between 1.4 and 1.5 and between 1.5 and 1.6.
The biggest differences that could cause problems that I can think of is that enum became a keyword, but that would only effect a 1.5+ JVMs when loading an older class file (which doesn't seem to be what you will be doing). The other thing is annotations. The above links seem to suggest everything would be fine, but I would be wary about what would happen if an older JVM loaded up a class with runtime annotations.
Other than that I don't think there have been any bytecode changes between the first version of java and java 6. Meaning the only problems you should encounter are changes to functionality the API or deprecations (listed in the links above).
As long as you aren't using reflection, the only major problem you could have from differing bytecode versions is the ACC_SUPER flag.
In very early versions, invocation of superclass methods was not handled correctly. When they fixed it, they added a new flag to the classfile format, ACC_SUPER to enable it, so that applications relying on the old, broken, behavior were not affected. Naturally, using a class that doesn't contain this flag could cause problems.
However, this is ancient history. Every class compiled in 1.4 and later will have the flag, so this isn't a problem. Bytecode wise, the only major differences between 1.4 and 1.6 are the addition of optional attributes used to store metadata about inner classes, generics, annotations, etc.
However, these don't directly affect the bytecode execution. The only way these have an affect is if you access them through reflection. For instance, java.lang.Class.getDeclaredClasses() will return information from the optional attribute InnerClasses.

Should I be concerned using AWTUtilities.setWindowShape()?

I am using the AWTUtilities class in my application to create custom window shapes. As far as I know, there is no other way to do it. It is a requirement.
The javadoc generation gives me this error:
warning: com.sun.awt.AWTUtilities is Sun proprietary API and may be removed in a future release
What exactly does this mean? I can use it, but it may stop working with any release? Why put it in, then? More importantly, and the real question here, if Sun takes it out, will they likely replace it with another way to do the same thing? Is that what the warning is for?
I suppose I could just check for the presence of the AWTUtilities class before calling the code. But that's just obnoxious if I don't need to do it.
Does anyone have any experience with similar classes? Were they eventually accepted into the API and the warning removed or replaced with another method of doing the same thing? Do I need to be concerned about this?
FYI, I have read this:
How to distribute AWTUtilities
The Oracle documentation states:
Note: the com.sun.awt.AWTUtilities class is not part of an officially supported API and appears as an implementation detail. The API is only meant for limited use outside of the core platform. It may change drastically between update releases, and it may even be removed or be moved in some other packages or classes. The class should be used via Java Reflection. Supported and public API will appear in the next major JDK release.
JDK 7 has been a long time coming so it could be awhile. Whether you should use it is a risk management question that only your company can answer. If we are talking about an internal application where the deployed JRE can be guaranteed then you are not going to have a problem because you can guarantee a compatible JRE. If we are talking about deploying to external customers then you need to have a support plan if this provisional API ever changes.
A stable way to do this would be to create a Shell in SWT as per this snippet and then use the SWT_AWT bridge to get a Frame to use in your application:
java.awt.Frame frame = SWT_AWT.new_Frame(shell);
If you are just deploying to a single platform (like Windows) then tossing a single SWT jar plus the native library. If you are targeting multiple platforms then this becomes a pain.
So those are the two choice: deal with the AWTUtilities risk or use the SWT_AWT bridge.
EDIT:
Some time has passed and Java 7 is out. There is documentation on the officially supported way to accomplish this in the Java Tutorials. The section "How to Implement a Shaped Window" at the bottom gives an example. This of course assumes you can mandate Java 7
You don't need a new Frame object, you can only use
this.setShape(shape);
or your frame name like this
Frame1.setShape(shape);
a lot of AWT methods has been applied to java.awt.Frame

Categories

Resources