Solve Jar Hell (JDK10?) - Java SE (Archived)

i think that this alone even if 80/20 solution would be a big productivity boost for non trivial applications that requires more than 10 JAR files and have cascading JAR dependencies.
what i want is some way to declare that my app requires JAR of this version (or newer) and each JAR file can also declare what it requires - when JVM is started with special option it is then doing full dependency check and classloader throws exception if there are unfulfilled or conflicting dependencies.
i think current package versioning could be extended for more details see: http://www.extreme.indiana.edu/~aslom/blog/java/2003/02/20/JavaPackageVersioningIsNotEasy.html
this change [b]alone[/b] is 10x more valuable than generics and i would not mind to call it then JDKX and skip version 6-9 :)
thanks,
alek

I suggest you write an application (in java) that opens a Jar and loads (creates a Class object) each .class file in there.  Each exception you get means you miss a dependency; print missing class name and your done.
Should be easy enough to create.  Why don't you create it and make it open source :)
Submit it to Maven if you like!  (if its not already available)

There is another thread "Administration of Libaries" which you may want to refer to. Maybe if we can have sufficient support, Sun would do something about it.

Judging by the luke-warm response to this request, I guess that solving JAR-Hell is of lesser priority to most of the developers around here. But, if you feel that solving JAR-Hell is an important issue, please indicate your approval in this thread so that Sun may notice it. If there are sufficient votes, then we can write a RFC for this purpose.

Quoting: [i]A bug first appears in some version of a vendors package and may or may not continue to be a problem in subsequent versions.....[/i]
damn it, so your rationale is: let's extend "feature backward compatible" to "bug backward compatible"
And this is supposed to solve any hell? (Exaggerating :-))
Anyway, [b]I agree[/b] that package/jar/module dependecies and requirements should be more precisely specifiable and application/runtime should be able to verify these requirements.
[b]Off topic:[/b] Ad. your sarcastic attack on generics :-): jar hell can be solved right now by properly configuring your runtime environment, that's all. For generics, we need compiler and JVM's support. As for value: you configure your runtime properly only once and you're done while generics can help you throughout the whole development process

My first gripe is the number of people who don't bother to put any form of version information in their Manifests.
Once you have sensible version information, WebStart is a great way of ensuring that you get exactly what you expect in your class path.

I couldn't agree more. Look at Xerces, Xalan, even Sun supplied Java libraries. None of them have version information. I think this is partly because under the current situations, it is useless. I have to write custom classloader, non standard extensions and all just to ensure that I load the correct classes. I cannot use WebStart in many cases (server-side).
My requirement is this:
1. I should be able to say what version of a Java package I want in my code (I am assuming that a Java package, and not class is the basic unit of versionable entity), and use the classes from that version.
E.g.
#Version(EQUALS_OR_GREATER, 1.2)
import org.apache.xpath.*;
2. It should be possible to have multiple versions of the same packages in the classpath, and the JVM should load classes from the specified package version.
3. The JVM should support the package management, and dependency tracking by default. I do not want to specify configurations, classpath hacks to get it working. If it is not easy to use, nobody will use it.
We need to make Java run-time behaviour much more reliable. I don't know how JVM sharing can be done gracefully and reliably until the package versioning is fixed. Versioning becomes more and more necessary as the number of Java components increase.

> I couldn't agree more. Look at Xerces, Xalan, even
> Sun supplied Java libraries. None of them have
> version information. I think this is partly because
> under the current situations, it is useless.
Not entirely useless. My JNLP deployment process extracts whatever version information is present and uses this to form the file name (so that I have things like forms__v1.0.2.jar and forms__v1.0.4 in my JNLP server area), and inserts the relevant version into the JNLP file being deployed. Unfortunately unless I insert the version myself, antlr.jar remains just as it is.
> classes. I cannot use WebStart in many cases
> (server-side).
In my opinion WebStart ought to be extended so that it can be used for server side processes and command line applications, everywhere in fact. There is no reason why the JNLP mechanism can't be used in these cases, just that the current client deployed with Java doesn't permit it.

But this still does not solve multiple versions problem.
Suppose I use Xerces 1.0 for my application, and the plugin from my customer uses Xerces 2.0. At present, it is not possible because only the classes encountered first are used. Thus, I cannot have multiple versions of same class in the same JVM.
I think what we need is an integrated, whole hearted support within JVM.

Related

Distributing java applications

Hey all I have a couple of questions about distributing java files and hope to get some insight about this.
Firstly, I have read about packaging files into jar files and distributing them, but there would be a risk of your class files being decompiled and all, or your program getting slow because of encrypting jar files. I would therefore like to know if class files can be got from installation files created by installers, since, as I understand, the installer programs use jar files.
Secondly, if I have different java add ons being used in my program such as JMF or JAI, how can I add these to my final installation (since I think the machine for deployment might need them).
Finally, if I have a number of class files, is there any other way, apart from using the jar commands in dos that I can add these files? I tried using winrar and naming the file with a .jar extension but the file cannot be run. I get the "data is corrupt" or something error.
Hope I can get some valuable feedback. Thank you 
joshmo wrote:
Firstly, I have read about packaging files into jar files and distributing them, but there would be a risk of your class files being decompiled and all, or your program getting slow because of encrypting jar files. I would therefore like to know if class files can be got from installation files created by installers, since, as I understand, the installer programs use jar files. don't bother. Noone is interested in your code.
If it were so good and special that people would want to decompile it you'd know what to do about it and wouldn't have to ask.
Secondly, if I have different java add ons being used in my program such as JMF or JAI, how can I add these to my final installation (since I think the machine for deployment might need them).Look at the distribution license for those. 
>
don't bother. Noone is interested in your code.
If it were so good and special that people would want to decompile it you'd know what to do about it and wouldn't have to ask.Well it is not about someone wanting my code. Its about the knowledge on how to prevent it and the little research I did showed that encrypting them or something would not be really effective. Well from a poster with your number of posts I would not expect such an answer from you and would expect you to know that asking how something should be prevented does not mean you have alot to guard. It is wanting the knowledge of how you can help others or even yourself to better secure themselves. 
>
don't bother. Noone is interested in your code.
If it were so good and special that people would want to decompile it you'd know what to do about it and wouldn't have to ask.Well it is not about someone wanting my code. Its about the knowledge on how to prevent it and the little research I did showed that encrypting them or something would not be really effective. Well from a poster with your number of posts I would not expect such an answer from you and would expect you to know that asking how something should be prevented does not mean you have alot to guard. It is wanting the knowledge of how you can help others or even yourself to better secure themselves. 
Here's how to prevent people from getting at the code: don't distribute it.
If people are going to run your code, they have to be able to read it. That's what a computer does, it reads code and executes it. If the user can read the code for purposes of executing it, they can read it for purposes of reverse engineering it.
Any security you ever gain by making program code less accessible will be negligible.
If for some reason you really fear people seeing your code, then only write server applications, and provide very narrow interfaces to the execution of the code. For example, write web server apps with only very plain HTML interfaces and secure the hell out of the web server. This is not 100% of course -- nothing is -- but this is the closest practical approach. 
joshmo wrote:
...distributing java ...Use [Java Web Start|http://java.sun.com/javase/technologies/desktop/javawebstart/index.jsp] (JWS).
Secondly, if I have different java add ons being used in my program such as JMF or JAI, how can I add these to my final installation (since I think the machine for deployment might need them).Add them to the run-time classpath of the application. Either directly in the original JNLP (JWS launch file) or as an 'extension' that might easily be used by a number of applications.
Finally, if I have a number of class files, is there any other way, apart from using the jar commands in dos that I can add these files? Use ant (to Jar them). Ant is built-in to most IDEs, but I installed it alone, so I can run it from the command line (or invoke it from a simple text editor, when pointing to a build.xml file). 
AndrewThompson64 wrote:
joshmo wrote:
...distributing java ...Use [Java Web Start|http://java.sun.com/javase/technologies/desktop/javawebstart/index.jsp] (JWS).
Secondly, if I have different java add ons being used in my program such as JMF or JAI, how can I add these to my final installation (since I think the machine for deployment might need them).Add them to the run-time classpath of the application. Either directly in the original JNLP (JWS launch file) or as an 'extension' that might easily be used by a number of applications.Both KMS and JAI require native components, so just adding some jars isn't going to do that.
The respective installers will have to be run on each client as part of the application installation.
Finally, if I have a number of class files, is there any other way, apart from using the jar commands in dos that I can add these files? Use ant (to Jar them). Ant is built-in to most IDEs, but I installed it alone, so I can run it from the command line (or invoke it from a simple text editor, when pointing to a build.xml file).I'd say 'run the ja command from a Unix shell'. Or to realise that jar won't even run under DOS, it requires a 32 bit or better operating system and DOS is 16 bit. 
jwenting wrote:
AndrewThompson64 wrote:
joshmo wrote:
...distributing java ...Use [Java Web Start|http://java.sun.com/javase/technologies/desktop/javawebstart/index.jsp] (JWS).
Secondly, if I have different java add ons being used in my program such as JMF or JAI, how can I add these to my final installation (since I think the machine for deployment might need them).Add them to the run-time classpath of the application. Either directly in the original JNLP (JWS launch file) or as an 'extension' that might easily be used by a number of applications.Both KMS and JAI require native components, so just adding some jars isn't going to do that.
The respective installers will have to be run on each client as part of the application installation.I am not sure if those statements above amount to "JWS cannot do this", but on the vague assumption they do, note the following..
1) Natives can be added to the run-time class-path of JWS apps. And better than most installers, JWS can 'partition' the native download specific to the OS, and it can update them as the need arises. The natives are (normally, unless an installer(4) ensures otherwise) private to the application, so side-step 'DLL hell'. See the [nativelib element|http://java.sun.com/j2se/1.4.2/docs/guide/jws/developersguide/syntax.html#resources] for further details.
2) There is a [web-start extension|https://jai-webstart.dev.java.net/] available for JAI.
3) I have previously developed JWS extensions for the JMF (both core Java and performance pack - which includes Win and Unix natives). There are actually two ways to deploy JMF using web-start, one involves simply calling the original binary installer(4) supplied, from an installer-desc element referenced in the main JNLP. I did not follow that route, since it ends with the installer recommending the user 'reboot to proceed'. That step was found to be unnecessary when simply adding the class and native Jars to the JNLP launch file resource section directly.
4) In case it has not become clear yet, JWS can invoke native (or core Java..) installers the first time the application is invoked. For more details, see the [demo of the ExtensionInstallerService|http://pscode.org/jws/api.html#eis].
What is 'KMS'? 
do check the JWS and JAI installer licenses. If they're at all like the JRE/JDK license you're not allowed to pull the distributions apart and distribute pieces as needed with some application.

Lazy downloads, parts & media

Recently I have been mucking about with the 'lazy'
download ability of web start resources. There is
still a great deal I need to figure out, but I 'solved' one
aspect of my concerns just now.
Generally, lazy resources are triggered for download
by being a class found in a part specified in a package
element, or any part connected with it.
Consider this case..<jar href="animalcode.jar" part='animal' download='lazy' size='861'/>
<package name="test.pkg1.AnimalImage" part="animal"/>
<jar href="animalmedia.jar" part='animal' download='lazy' size='368231'/>..as soon as test.pkg1.AnimalImage class is called
in code, the web start manager uses the part attribute
of the package element to identify it as residing in either
animalcode.jar or animalmedia.jar, and loads both.
This is fine if you have a class for each piece of media,
but I wondered how the developer might trigger the download
of media itself, that was not associated with any class in
particular.
The documentation on the package element suggests it is
only for pakages and classes, but on a hunch, I tried this..
<jar href="animalmedia.jar" part='animal' download='lazy' size='368231'/>
<package name="image.DCP_7940.jpg" part="animal"/>..which identifes to the web start manager that the
image (path image/DCP_7940.jpg) of a guinea pig
is in animalmedia.jar.
Since I can find nothing in the documentation that
supports that should work, I am a little cautious
about relying on it though.
Can anyone clarify if that is 'defined behaviour' for
web start? (Links would be very much appreciated) 
Although there is no doc clarification I can point to, we (the Sun Deployment teams) interpreted the spec to imply that this should work (ie, it should work for packages, classes, and other resources).
So for javaws 1.5.0_02 and beyond (it is broken in several earlier releases) this will work.
For Java 6 and beyond, you can just skip all the package and part attributes, and use the Jar Indexing method defined in Java 1.3. The Jnlp Spec wr\as written before the Java 1.3 specification, and was trying to solve this same problem that was addressed by Jar Indexing in Java 1.3. Unfortunately, support for Jar Indexing was not added to Java Web Start till version 6 (due to GA by end of this year.)
/Andy 
(..specify part for media)
Although there is no doc clarification I can point
to, we (the Sun Deployment teams) interpreted the
spec to imply that this should work (ie, it should
work for packages, classes, and other resources).I like that kind of attitude. :-)
I'd like to pin down something a little further though..
does 'resources' include natives?
I have progressed to trying an example of lazy download
of DLL/SO files (it is failing due to unrelated problems I
have yet to track down).
So for javaws 1.5.0_02 and beyond (it is broken in
several earlier releases) this will work.Does this mean it will not work for any pre 1.5 VM?
For Java 6 and beyond, you can just skip all the
package and part attributes, and use the Jar Indexing
method defined in Java 1.3. I have been discussing jar indexing with a friend via email,
and have my reservations about it. Particularly I do
not like the idea of having to specify a 'master index'
in the first jar that lists all resources - is that a correct
understanding though? To get lazy downloads to work
with Jar indexing would require a master index?
...The Jnlp Spec wr\as
written before the Java 1.3 specification, and was
trying to solve this same problem that was addressed
by Jar Indexing in Java 1.3. Unfortunately, support
for Jar Indexing was not added to Java Web Start till
version 6 (due to GA by end of this year.)Yeah.. I'm some time off even bothering to look at 1.6,
let alone developing in it and asking my users to install it,
I am much more interested in determining what can be
achieved within the current 1.5 and earlier VM's.
(I've also had my friend chewing my ear off about
how wonderful 1.6 is!).
Thanks for your response, BTW - I had noticed that you
were one of the few responders to be taken seriously
around these parts, but had not realised you were on the
dev. team!

Does j2se element in JNLP support non-standard options

I am trying to use options like -Xbootclasspath while starting the application to set search path for bootstrap classes and resources. Going by the documentation, it appears j2se supports options like initial-heap-size, max-heap-size but I could not find anything on Xbootclasspath.
Any pointers are welcome.
Thanks,
Raman. 
HI,
I'm facing the same problem. I'd like to WebStart enable an existing application which needs the -Xbootclasspath on startup. If I understood the Developer's Guide correctly (http://java.sun.com/products/javawebstart/docs/developersguide.html#dev) there is no way to set a bootclasspath due to security restrictions. Anyway, this is not cleary stated. 
No I'm sure you can't do this, it would open a huge security hole if you could. As webstart uses it's own classloaders it'd be pretty meaningless non the less.
If your trying to override the java or sun packages (eg for running LumberJack) your going to be bang out of luck, in any case it'd be prohibited by the Java 2 binary code license even if webstart allowed it.
Just an afterthought.. they'res nothing from stopping you from writing your own lancher to handle JNLP.. infact there's a couple of open source alternatives OpenJNLP, JavaURL etc..

locating the JVM from within native code

We have a Native application written in C and C++. It has a plugin system that loads C plugin shared library modules. One of these modules has to load the JVM, it is linked against it. This all works well, as long as jvm.dll is in %PATH% on windows or in $LD_LIBRARY_PATH in linux (the application is also used under OS X, but i dont know how it works there). The problem arises when deploying the application, as normal users have generally not set these paths.
Question: Is there a portable and GPL v2+ compatible way to automatically locate/load the JVM? Cause it would not be user friendly if everyone would have to set this path by hand, and it would cause a lot of error reports, no matter how well we would document the necessity to define this path.
Possible solution:
searching the net, i found a comment where someone suggest reading the code under dir launcher/ in the src.zip from the JDK home dir. Though this code is quite.. extensive, and i could not figure out if it is available under the GPL. Is it somewhere in OpenJDK aswell, and therefore GPL then? Is it a good way to use this code for an application, or are there simpler ways?
The optimum would be, if the main appication would not have to bother about locating the JVM, and it could be located within the plugin, but i guess that is not possible, as the shared library fails to load if the jvm is not in hte path in the first place. it would be acceptable to do the locating in the main application.
In case anyone is interested, the application is a strategy game, and the plugin allows AIs to be written in Java.
sorry if i am in the wrong subforum here, but i could not find a better fitting one. 
And why don't you just deploy it with the VM? Then setup the install so it sets the PATH before it starts your app?
What do you do if the VM is not installed at all?
Other than that on windows you can find the info in the registry. There might be something similar on linux. 
We will not pack it, because that would double the installer size of our application, and 90% of our users will not use the plugin that uses Java.
If the VM is not installed, this plugin is not usable, whihc manifests in either (preferably) an error message, or crash of the application when it tries to load the plugin.
I looked at the launcher sources a bit, and i found out about the registry key like this. On Unix, the launcher is not using anything comparable, and seems to rely on the relative location of the jvm to the bin dir, but i could assemble a list of common paths under which java is installed in different distributions.
It is just sad somehow, that there is no easy solution for that. SUN should provide an independant pair of header/source files, once for windows and once for the rest. These could contain functions like GetJVMLocation(const char* requiredVersion, ...) and maybe AddJVMDirToLibrarySearchPath(...).
I will try to do this myself now, and possibly pusblish the code somewhere.
i found some tutorials, they may help others, so i list them here:
http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html
http://java.sys-con.com/node/45840
http://www.ociweb.com/jnb/jnbJul2004.html
if you need multi platform support, you could get the OpenJDK sources, and search for the file java_md.h and java.h (there are multiple ones of each). From there, you could fight your way through.
I will try to locate and then dynamically load the JVM, eg. with LoadLibrary on windows, instead of using -ljvm. 
robinV wrote:
We will not pack it, because that would double the installer size of our application, and 90% of our users will not use the plugin that uses Java.
If the VM is not installed, this plugin is not usable, whihc manifests in either (preferably) an error message, or crash of the application when it tries to load the plugin.
I looked at the launcher sources a bit, and i found out about the registry key like this. On Unix, the launcher is not using anything comparable, and seems to rely on the relative location of the jvm to the bin dir, but i could assemble a list of common paths under which java is installed in different distributions.
It is just sad somehow, that there is no easy solution for that. SUN should provide an independant pair of header/source files, once for windows and once for the rest. These could contain functions like GetJVMLocation(const char* requiredVersion, ...) and maybe AddJVMDirToLibrarySearchPath(...).I think your view of your user based is badly mixed.
You are approaching this as though your user base is not knowledgeable enough to even know whether they have java installed and yet at the same time you expect this user base to be working on linux and/or to be completely happy when an odd error dialog or even a crash occurs.
I seriously doubt that casual users will be using linux. Casual users on windows are not going to be happy with a error/crash when they "know" that they have java installed. You can verify that by reading through countless posts here where casual users have installed/uninstalled java multiple times in an attempt to get a third party app to work.
In terms of locating java it requires searching the file system. The entire file system. A knowledgeable person might put it anywhere.
A much, much simpler solution is to create an installer that asks the user if they want the plugin, note that it needs java, and require them to provide the path. If the user does not want the plugin or they cannot figure out the correct path to java then that functionality is disabled. You can provide a simple path check in the same install and use the first vm, if found, from that. 
It is not acceptable that the app crashes, of course, and the error would be, that the plugin would not work, and a log entry plus text message in a GUI directly to the user is issued, but the game would go on. This is How this app handles all errors, this would be acceptable. As so few users will use this plugin, we would like them to have as little contact with it as possible. Also, we ship to a lot of distros on linux, which would make it cumbersome to have a script start after installation, where we would ask for the location of Java. Though, we want to include the plugin in a default install for some reasons.
i discuss this with other devs of the project. together, we have a quite good view of the users of our software, as you have it with the users of java.
We already have some, and will have more plugins that use other languages, and will need the path to the Mono VM, python, ruby, ...
The application is quite complex already, and therefore we want to automate as much as possible, so the user will not have to configure even more things when installing. choosing the java location will be enabled through a config file, for the knowledgeable, but the app should do everything possible to find it automatically.
Therefore, the registry seems to be a good thing on windows, and i will probably check the JAVA_HOME env var aswell (is JRE_HOME a standard too?). on linux, i will check a few common locations. of course, searching the whole file system would be safest, and i might add it as a last thing to try, but it would most likely take way too much time. 
This problem is solved. i wrote custom native code, using parts of java.c an java_md.c from the OpenJDK invocator. Works well!
On windows, searching works like this:
- check a config file for a path to a JVM
- check the registry
- look for env var JAVA_HOME
On the rest:
- check a config file for a path to a JVM
- look for env var JAVA_HOME
- try 'which java'
- check a list of file system globs with common locations, eg:
/usr/local/java-?-sun
/usr/share/jdk*
if someone comes around that is interested in this, you can get the code from the spring game engine project sources:
http://github.com/spring/spring/tree/master
thanks anyway jschell!

Using java.util.logging.Logger with older versions of Java

My university are backward, and they seem to refuse to use a version of a product newer than at least two versions ago. As such a lot of the classes I have developed, using java.util.logging.Logger, won't run on their machines. Unlike the XML pack, that you can download seperately, the Logger seems to be entirely integrated with 1.4. I was wondering if anyone knew if this could be seperated into a seperate jar file or something.
Otherwise I'll just generate a pretend logger that just prints it to standard out or error. Ooh they make me so mad :).
Thanks. 
You might want to use Log4J from the Jakarta Project instead of the java.util.logging package if you need to support earlier versions of Java. Check it out at http://jakarta.apache.org/log4j/docs/index.html.
Shaun 
Jakarta Commons logging facility is a good choice as it can allow you to write code that remains unchanged yet can leverage java.util.logging, log4j, and other logging facilities.
Or, take a look at LumberJack, a java.util.logging facility implemented for pre-1.4 JDK's. It's at http://sourceforge.net/projects/javalogging/ 
are you sure you cannot use the classes from a newer version. You can put those classes in your own directory. If there ar some other classes that need to be from the newer version, you can include them, also in your project. It is important that your project directory to be placed in the classpath variable before the jdk jars.
(this solution might not work) 
are you sure you cannot use the classes from a newer
version. You can put those classes in your own
directory. If there ar some other classes that need to
be from the newer version, you can include them, also
in your project. It is important that your project
directory to be placed in the classpath variable
before the jdk jars.
(this solution might not work)I doubt that is worth trying.
First, although it probably does not apply in this case, you are not allowed to distribute part of a JVM. So you could never use this solution in a commercial application.
Secondly the Java API does change. And every execution path that might use the changed code would have to be tested. That is going to take a lot of work. Keep in mind that the logging api uses java.lang.String and java.lang.String definitely changed in 1.4 and almost every class in the Java API uses it.

Categories

Resources