Showing posts with label Jar. Show all posts
Showing posts with label Jar. Show all posts

Wednesday, May 27, 2009

Java Jar File Naming Conventions and Examples.

util.jar is the worst jar file name I can think of. All I know is it contains some utility/helper classes. But it is unclear if they belong to an application server, or a framework, or any application sub-systems. You will need to ask someone or some docs to know what it is. It's part of the DataDirect JDBC Driver distribution.
On the other hand, good jar file names are always self-explanatory, for example: struts.jar, jboss-system.jar, commons-pool-1.1.jar
Some thoughts on jar file naming conventions:
1. Always use extension ".jar", not ".zip"
Theoretically, jar files can have any extension or no extension at all. If you specify it in the system classpath, it should be loadable. The problem is with automatic library detection and loading by containers and frameworks. It's expensive to scan all files so some sort of extension restriction is needed. For this reason, J2EE/JavaEE platform spec requires all library jar files use ".jar" extension, such as WEB-INF/lib/mybeans.jar.
2. Use hyphen (-) instead of underscore (_) as word separator
First, it's easier to type - than _; secondly, when the file name is underlined (e.g., in a hyperlink), the _ is invisible. Hyphen has been shunned in file names partly because it is an illegal character in java identifier. But this concern is unwarranted.
3. Append version number if distributed standalone
because they can be dropped into any applications, which may need specific versions. We don't want users to have to compare file size or extract some META-INF files to know its version. Some examples: hibernate3.jar, commons-logging-1.0.3.jar, and
log4j-1.2.8.jar.
4. Don't append version number if bundled inside other larger deliverables
because the enclosing deliverables, such as an application server (e.g., JBoss 4.0.4, jakarta-tomcat-5), a tool(e.g., apache-ant-1.6.5), aleady have the version numbers, thus no version number for jboss.jar, catalina.jar, and ant.jar.

A New Option in Jar Command in JDK 6

DK 6 adds a new feature to the jar command: e. Other options of the jar command are still the same. This is the partial usage from JDK 6 beta 2:
C:\tools\jdk6\bin>jar
Usage: jar {ctxui}[vfm0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...
Options:
...
-e specify application entry point for stand-alone application
bundled into an executable jar file
...
For example, I run jar command to package a self-contained application in a jar file:
C:\ws\nb\scrap\build\classes>C:\tools\jdk6\bin\jar cvfe ..\..\dist\hello-world.jar com.javahowto.test.HelloWorld com
added manifest
adding: com/(in = 0) (out= 0)(stored 0%)
adding: com/javahowto/(in = 0) (out= 0)(stored 0%)
adding: com/javahowto/test/(in = 0) (out= 0)(stored 0%)
adding: com/javahowto/test/HelloWorld.class(in = 572) (out= 348)(deflated 39%)
Then I can distribute hello-world.jar to users, who can run hello-world app like this:
C:\download\hello>java -jar hello-world.jar
Hello world!
Users can run it with any version of java; it doesn't have to be JDK 6. What the extra e option does is simply adding a Main-Class entry in the jar's META-INF\MANIFEST.MF:
Manifest-Version: 1.0
Created-By: 1.6.0-beta2 (Sun Microsystems Inc.)
Main-Class: com.javahowto.test.HelloWorld
This new feature is helpful when packaging simple self-contained apps, and application client modules in J2EE/JavaEE, both of them require a Main-Class entry in MANIFEST.MF. So I don't have to create one beforehand, or have Apache Ant generate one.

Tuesday, February 17, 2009

A New Option in Jar Command in JDK 6

JDK 6 adds a new feature to the jar command: e. Other options of the jar command are still the same. This is the partial usage from JDK 6 beta 2:

C:\tools\jdk6\bin>jar
Usage: jar {ctxui}[vfm0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...
Options:
...
-e specify application entry point for stand-alone application
bundled into an executable jar file
...
For example, I run jar command to package a self-contained application in a jar file:
C:\ws\nb\scrap\build\classes>C:\tools\jdk6\bin\jar cvfe  ..\..\dist\hello-world.jar com.javahowto.test.HelloWorld com
added manifest
adding: com/(in = 0) (out= 0)(stored 0%)
adding: com/javahowto/(in = 0) (out= 0)(stored 0%)
adding: com/javahowto/test/(in = 0) (out= 0)(stored 0%)
adding: com/javahowto/test/HelloWorld.class(in = 572) (out= 348)(deflated 39%)
Then I can distribute hello-world.jar to users, who can run hello-world app like this:
C:\download\hello>java -jar hello-world.jar
Hello world!
Users can run it with any version of java; it doesn't have to be JDK 6. What the extra e option does is simply adding a Main-Class entry in the jar's META-INF\MANIFEST.MF:
Manifest-Version: 1.0
Created-By: 1.6.0-beta2 (Sun Microsystems Inc.)
Main-Class: com.javahowto.test.HelloWorld
This new feature is helpful when packaging simple self-contained apps, and application client modules in J2EE/JavaEE, both of them require a Main-Class entry in MANIFEST.MF. So I don't have to create one beforehand, or have Apache Ant generate one.

Something You May Not Know about Jar Command

1. jar command can also operate on zip files. I usually run jar tvf hello.zip to quickly view its content, without starting up the WinZip program. jar xvf hello.zip should also be able to expand the target zip files. I find it hard to memorize Unix zip/unzip command line options, so I just use jar tvf/jar xvf instead. For example:

C:\tmp>jar tvf eclipse-SDK-3.2RC7-win32.zip
2. jar tvf can selectively list table of contents for archive. I used to run jar tvf j2ee.jar | grep javax/servlet/http to search for servlet classes in j2ee.jar. Replace grep with findstr on Windows. In fact, I don't need grep or findstr; I can just run this command:
jar tvf j2ee.jar javax/servlet/http
Note that the search criteria are matched against the beginning of all entries in jar file. It uses String.startsWith(what) rather than String.contains(what). So this command jar tvf j2ee.jar ejb will not return any matching entries, though jar tvf j2ee.jar javax/ejb will return all ejb classes. The search is also case-sensitive.

If you want case-insensitive search, or match by any parts (not just the beginning) of entries, you still need to use jar tvf my.jar | grep -i aNynAmE

3. You can extract selected entries from a jar file. For instance, if you only want to view the meta-inf/manifest.mf file, you can
C:\Sun\AppServer\lib>jar xvf j2ee.jar META-INF/MANIFEST.MF
inflated: META-INF/MANIFEST.MF
Or using a backslash instead of a forward slash:
C:\Sun\AppServer\lib>jar xvf j2ee.jar META-INF\MANIFEST.MF
inflated: META-INF/MANIFEST.MF
The entry names are case sensitive, and so the following will not extract anything:
C:\Sun\AppServer\lib>jar xvf j2ee.jar meta-inf/manifest.mf
Of course, you can always double-click the entry to view it in WinZip, fileroller, or other tools.

4. You can choose not to have manifest file when creating a jar file, using M option:

jar cvfM no-meta.jar A.class
adding: A.class(in = 405) (out= 279)(deflated 31%)
Note: it's upper-case M. Lower-case m has a different meaning.

5. You can specify your own manifest file when creating a jar file, using m option:
jar cvfm my-meta.jar my-meta-inf\my.mf A.class
added manifest
adding: A.class(in = 405) (out= 279)(deflated 31%)
The option used here cvfm tells the jar command that the destination file (f) will come next and then custom manifest file (m). I can also specify them in a different order:
jar cvmf my-meta-inf\my.mf my-meta.jar A.class
added manifest
adding: A.class(in = 405) (out= 279)(deflated 31%)
It's lower-case m. Upper-case M has a different meaning.

6.META-INF/MANIFEST.MF file in source files is always ignored.
jar cvf ignore.jar A.class META-INF
added manifest
adding: A.class(in = 405) (out= 279)(deflated 31%)
ignoring entry META-INF/
adding: META-INF/LICENSE.txt(in = 2657) (out= 1185)(deflated 55%)
ignoring entry META-INF/MANIFEST.MF
When it comes to manifest files for new jar file, you only have 3 options:
  • Do not specify any manifest-related options and use the default MANIFEST.MF

  • Use option M not to include a manifest file

  • Use option m to use a custom manifest file. Inside the jar file, this file will always be named MANIFEST.MF under META-INF directory. Outside of the jar file, this custom manifest file can be anywhere and have any name.
7. If you unjar an archive, do nothing, and then jar it up again, the resulted new archive may not equal to the original one. And applications using this new archive may not work correctly because of the wrong manifest file. The original jar may have a custom manifest file, which is expaned into META-INF/MANIFEST.MF. But when you jar these files up again without using cvfm option, this custom manifest file is ignored and a default MANIFEST.MF is included.

8. jar command options can start with optional -. jar tvf a.jar is the same as jar -tvf a.jar

9. You would usually use relative paths for source files, relative to the current directory. These relative paths will be preserved inside the target jar file. For example, jar cvf \tmp\b.jar com\javahowto\test\ will create the directory tree com\javahowto\test\ inside the target jar, and include all files under \com\javahowto\test\.

If you use absolute paths for source files, jar will copy the absolute paths inside the jar file, which is not what you want. For example,

C:\tmp>jar cvf a.jar C:\tmp\A.class
added manifest
adding: C:/tmp/A.class(in = 405) (out= 279)(deflated 31%)
10. If source files are not located in the current directory, you can use -C option to tell jar command to implicitly change to another directory and then include files there. For example,
C:\ws\nb\scrap\dist>jar cvf hello-world.jar -C ..\build\classes com\javahowto\test
11. If you use -C ../build/classes option and want to include all files under ../build/classes, use . (dot) to represent all files there. Note that you can't use *, which will resolve by OS to all files to the current directory. For example,
C:\ws\nb\scrap\dist>jar cvf hello-world.jar -C ..\build\classes .
The following example (using -C and *) will ignore -C option and instead include all files in the current directory, which is not what we want:
C:\ws\nb\scrap\dist>jar cvf hello-world.jar -C ..\build\classes *
..\build\classes\com\hello-world.jar : no such file or directory
added manifest
adding: scrap.jar(in = 20487) (out= 7472)(deflated 63%)
12. There are 3 types of paths in jar command:
  • path to the destination jar file, either relative or absolute path is fine. In fact, any format is ok as long as it can be correctly resolved by the OS

  • path to the manifest file, if m option is present. Either relative or absolute path is fine. The same as destination file.

  • multiple paths to source files. They should be relative to the current directory, unless -C option is present. In that case, all source files should be relative to the value of -C option.
If you don't like using -C option, I'd suggest you always cd into the parent directory of all source files, and then run jar command.

13. It is not possible to include source files from multiple different parent directories. But you can always first copy them into a common parent directory. Jar task in Apache Ant is more flexible and can accommodate almost all use cases.

14. In JDK 6 or newer version, you can use e option to specify an entry-point class (Main-Class in META-INF/MANIFEST.MF) for self-contained applications packaged in a jar file. See this post for details.

Java Jar File Naming Conventions and Examples

util.jar is the worst jar file name I can think of. All I know is it contains some utility/helper classes. But it is unclear if they belong to an application server, or a framework, or any application sub-systems. You will need to ask someone or some docs to know what it is. It's part of the DataDirect JDBC Driver distribution.

On the other hand, good jar file names are always self-explanatory, for example: struts.jar, jboss-system.jar, commons-pool-1.1.jar

Some thoughts on jar file naming conventions:

  1. Always use extension ".jar", not ".zip"
    Theoretically, jar files can have any extension or no extension at all. If you specify it in the system classpath, it should be loadable. The problem is with automatic library detection and loading by containers and frameworks. It's expensive to scan all files so some sort of extension restriction is needed. For this reason, J2EE/JavaEE platform spec requires all library jar files use ".jar" extension, such as WEB-INF/lib/mybeans.jar.

  2. Use hyphen (-) instead of underscore (_) as word separator
    First, it's easier to type - than _; secondly, when the file name is underlined (e.g., in a hyperlink), the _ is invisible. Hyphen has been shunned in file names partly because it is an illegal character in java identifier. But this concern is unwarranted.

  3. Append version number if distributed standalone
    because they can be dropped into any applications, which may need specific versions. We don't want users to have to compare file size or extract some META-INF files to know its version. Some examples: hibernate3.jar, commons-logging-1.0.3.jar, and
    log4j-1.2.8.jar
    .

  4. Don't append version number if bundled inside other larger deliverables
    because the enclosing deliverables, such as an application server (e.g., JBoss 4.0.4, jakarta-tomcat-5), a tool(e.g., apache-ant-1.6.5), aleady have the version numbers, thus no version number for jboss.jar, catalina.jar, and ant.jar.

Wednesday, November 12, 2008