I am learning about Java 9 from What's New in Java9 and one of the hot topics in the discussion is The Modular JDK.
Are JAR files modules?
How is a module different from a JAR file?
Module: A new language feature introduced in Java 9 (similar to class, interface, package, etc.) that consists of a collection of packages, similar to how a package consists of a collection of types.
JAR: An archive file format that bundles code and resources and which can be loaded by the JVM.
More specifically, a module is defined as follows:
In order to provide reliable configuration and strong encapsulation in a way that is both approachable to developers and supportable by existing tool chains we treat modules as a fundamental new kind of Java program component. A module is a named, self-describing collection of code and data. Its code is organized as a set of packages containing types, i.e., Java classes and interfaces; its data includes resources and other kinds of static information.
...
A module’s self-description is expressed in its module declaration, a new construct of the Java programming language.
...
A module declaration is compiled, by convention, into a file named module-info.class, placed similarly in the class-file output directory.
A module can be compiled into a Jar file, in which case the Jar file is labelled a modular Jar file:
Existing tools can already create, manipulate, and consume JAR files, so for ease of adoption and migration we define modular JAR files. A modular JAR file is like an ordinary JAR file in all possible ways, except that it also includes a module-info.class file in its root directory.
Some other differences between a module and a JAR:
Modules can require other modules in order to allow accessing dependent classes by the requiring module. A Jar has no such dependency concept.
A module can decide which classes and interfaces to export to other modules that require it. A Jar has no such encapsulation mechanism.
A module can be compiled into a modular Jar file, but some modules (e.g. JDK modules) are compiled into another format called JMOD.
The name of a JAR can be changed. As long as the JVM classloader finds the needed class on the classpath (which can be composed of a single JAR, multiple JARs, or a mix between directories or JARs), the name of the JAR file can be anything. However, the name of a module can be explicitly referenced in the declaration of other modules, and such the name defines it and cannot be changed freely.
Strictly speaking, a module is a run-time concept. As others have quoted from The State of the Module system:
A module is a named, self-describing collection of code and data. Its code is organized as a set of packages containing types, i.e., Java classes and interfaces; its data includes resources and other kinds of static information.
This is very similar to JARs, but...
JARs have no meaningful representation at run time
JARs are not "self-describing", which in this case means they do not have a name that the JVM cares about, can not express dependencies or define a proper API
This leaves the question, where do modules come from? There are various ways but the most prominent one for developers is the modular JAR. A modular JAR is just like a plain JAR, but it contains a module descriptor, a file module-info.class that was compiled from a module-info.java. It is that file that defines a module's name, dependencies, and APIs.
So there is a strong connection between JARs and modules: JARs are the containers from which the module system creates modules and (at the moment) each JAR can only contain a single module. It is important to note that even on Java 9 JARs do not have to be modular - plain JARs are totally fine.
Are JAR files Modules? How Module is different from JAR file?
No, a Java Archive is not a Module.
Just for an example, while classes of the same package could have been spread across JARs, the same package now can not be read from multiple modules.
A JAR is a file format that enables you to bundle multiple files
into a single archive file. Typically this contains the class files
and auxiliary resources associated with applets and applications.
on the other hand (I'd tried describing this here ~> java-module as well)
A module is a named, self-describing collection of code and data. Its
code is organized as a set of packages containing types, i.e., Java
classes and interfaces; its data includes resources and other kinds of
static information.
This also consists of the module declaration as specified with the help of module-info.java.
Each module definition is either
A module artifact, i.e., a modular JAR file or a JMOD file containing a compiled module definition, or else
An exploded-module directory whose name is, by convention, the module's name and whose content is an "exploded" directory tree corresponding to a package hierarchy.
As introduced with the module system, a modular image is composed of modules rather than JAR files.
Modularity is foreseen for with dynamic configuration in terms of Modular WAR file as well.
But for the ease of adoption of Modules a Modular JAR file, was introduced in JDK9, such that lets say for a module consisting of a module-info.java such that
module com.foo.bar { }
and other java classes as
com/foo/bar/alpha/AlphaFactory.java
com/foo/bar/alpha/Alpha.java
Existing tools can already create, manipulate, and consume JAR files. A modular JAR file is like an ordinary JAR file in all
possible ways, except that it also includes a module-info.class file
in its root directory. A modular JAR file for the above com.foo.bar
module, e.g., might have the content:
META-INF/
META-INF/MANIFEST.MF
module-info.class
com/foo/bar/alpha/AlphaFactory.class
com/foo/bar/alpha/Alpha.class
...
A modular JAR file can be used as a module, in which case its module-info.class file is taken to contain the module’s declaration.
It can, alternatively, be placed on the ordinary class path, in which
case its module-info.class file is ignored.
Related
For various historical reasons, I have an old java application which shares a local lib/ directory of library .JARs with some other applications. In this directory is a number of versioned copies of the same library, for example:
...
log4j-1.2.16.jar
log4j-1.2.17.jar
slf4j-api-1.7.5.jar
slf4j-api-1.7.21.jar
slf4j-log4j12-1.7.5.jar
slf4j-log4j12-1.7.9.jar
...
When my java app starts, how does it decide which .jar file to load? As far as I know, the CLASSPATH is just set to ./lib/. But it uses the Tanuki Service wrapper to start, so I'm not 100% sure of this.
I can't delete any of these existing .JARs, is there a way to specify exactly which .JARs my app will use ?
After this old application was patched, now I'm getting a NoClassDefFoundError, and I suspect the app is loading an older (or newer) version of a .JAR that conflicts with another library (BoneCP and slf4j).
Which jar first in classpath that is picked up when JVM classloader is looking for a class. So you can try to add those jars in different order to check which one breaks your application
If you are going to share lib directories like that, then each application needs to list the JAR files that it uses explicitly on the classpath. If you use a wildcard classpath entry (e.g. "lib/*"), then it is not specified which versions of the JARs will be used. The manual entry states:
Class Path Wild Cards
Class path entries can contain the base name wildcard character (), which is considered equivalent to specifying a list of all of the files in the directory with the extension .jar or .JAR. For example, the class path entry mydir/ specifies all JAR files in the directory named mydir. A class path entry consisting of * expands to a list of all the jar files in the current directory. Files are considered regardless of whether they are hidden (have names beginning with '.').
....
The order in which the JAR files in a directory are enumerated in the
expanded class path is not specified and may vary from platform to
platform and even from moment to moment on the same machine. A
well-constructed application should not depend upon any particular
order. If a specific order is required, then the JAR files can be
enumerated explicitly in the class path.
What is the relationship between package and jar file in java? Do you get one jar file for each package?
A package logically organizes your classes. For example, you can declare package com.stackoverflow in each of the source files to keep the all files in the same directory.
A JAR file lets you physically organize your classes. You can take any Java files and store them in a JAR file.
A JAR file may contain multiple packages, and multiple JAR files may contain files that belong to the same package. So, a JAR file is largely a way to store multiple class files in a single physical file.
Package consist of classes..
Jar : collection of packages and classes...
A package is a way of organizing Java types into groups of related types, and is part of the Java language. It doesn't exist as a resource or artifact, rather as a namespace, which means it's part of the type name.
A JAR is not part of the Java language but a file in a ZIP format. It contains loadable forms of Java types, i.e., class files, plus other files needed to deploy an application. Its purpose is to provide a deployment mechanism for Java code and resources.
It's like the difference between a chapter of a novel and a ZIP file containing a file representation of the novel. One is an abstraction, the other a file.
I am aware of usage of MANIFEST file in a mobile application, but am not aware of usage of same in a Java Application.
My guess say like, its being used to keep BUILD information only. Am I correct??
Is this Mandatory?If not, then what are the key benefits that we can draw with this?
manifest.mf carries attributes of the artifact. One of the most well known ones is for example the main class of the jar that is used to start the jar file when no other class is specified. Syntax:
Main-Class: classname
Other purposes are, for example, package sealing and package versioning. Check out the java tutorial about it:
http://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html
A manifest in a jar usually contains much less information than for example AndroidManifest.xml. It is quite lightweight and does not contain any build or packaging information.
This is because java has no good module system. So, a jar is not a module which might need a lot of configuration information (like a list of modules to which it has dependencies). Instead, a jar is just a bunch of classes with some configuration information. Hopefully, this will be fixed by project jigsaw (http://openjdk.java.net/projects/jigsaw/).
What is the simplest way to manage dependencies of Java classes to data files present in the classpath?
More specifically:
How should data dependencies be annotated? Perhaps using Java annotations (e.g., #Data)? Or rather some build entries in a build script or a properties file? Is there build tool that integrates and evaluates such information (Ant, Scons, ...)? Do you have examples?
Consider the following scenario:
A few lines of Ant create a Jar from my sources that includes everything found on the classpath. Then jarjar is used to remove all .class files that are not necessary to execute, say, class Foo. The problem is that all the data files that class Bar depends upon are still there in the Jar. The ideal deployment script, however, would recognize that the data files on which only class Bar depends can be removed while data files on which class Foo depends must be retained.
Any hints?
This is one of the many problems Maven has already solved with it's build, dependency, and resource management. Any maven project follows a standard directory layout which dictates where you should put your Data files: in the 'resources' directories. The conventional Maven directory structure is as follows...
/
/src/
/src/main/java/
/src/main/java/App.java
/src/main/resources/
/src/main/resources/my.prod.data.or.cfg.or.whatever
/src/test/java/
/src/test/java/AppTest.java
/src/test/resources/
/src/test/resources/my.test.data.or.cfg.or.whatever
/pom.xml
The benefit of this is that all files which are contained in the 'main' (prod) resources directories are available to your application at run-time from the Classpath. All of the 'test/resources' files are available to your code during build & unit test time but are NOT included in your final artifact.
I don't think a generic solution exists for the system you describe, however, I just had a stab at reading annotations on classes using ASM, since that is used by jarjar as well. It is not hard to read the annotation data that way (pass in a ClassVisitor to the accept() method on ClassReader, and do something useful on the visitAnnotation callback). This means you can either try and include your intended behavior to jarjar or you could add it as a custom step to your build process.
Can't you refactor your project so that you have submodules that each contain the relevant files for the project itself ; Bar class and Bar related files will be packaged in their bundle while Foo ones will packed into another?
Another possibility would be to use some package naming convention to be able to filter the files you want to see i your bundles.
What is a Class library in Java? Is it a collection of classes with in a package, or it is a package that has collection of classes?
I'm bit confused. ^_^
It's a collection of classes, usually bundled up in a jar file. All the classes may be in the same Java package, but they don't have to be. A class library in a jar file may also contain resources and meta-data that it needs (e.g. string translations, driver information for other frameworks etc).
Yes, class libraries are just sets of classes in a package.
They could be stored in a folder but mostly they are distributed in JARs (Java ARchives), which are just zipped up class files.
The JavaTM Archive (JAR) file format enables you to bundle multiple files into a single archive file. Typically a JAR file contains the class files and auxiliary resources associated with applets and applications.
You can get more information from this link