When Altering The Main Method Signature
When Altering The Main Method Signature
}
Output: No compilation error.
java.lang.NoSuchMethodError: main
Exception in thread "main"
Conclusion:
public static void main(String [] args)
This is the signature of the main method in Java. public access means that the
method can be called from outside. This is the first method to be called by the JRE
to start the execution, so it needs to be declared public.
static means that its a Class method and not an instance method. Since, this
method is called to start the execution, so we cant have it as an instance method.
Unless you start the execution, how will you create an instance? So, we must
declare this as a static method.
void means that the method returns nothing. The designers of Java thought that
the main method should not return anything and hence they made it mandatory to
declare the return type as void. It could have been int as is the case in C
language. But, this hardly adds any value. In C, a return value of 0 specifies
successful completion of the program, but in Java we have a far better and rich
Exception Handling mechanism, so we dont really need to rely on the return value
of the main method.
String[] args this represents the command line arguments passed. All the
arguments are stored in a String array and you need to type-cast it accordingly
before using in the program. This array is also 0-indexed and the first argument is
stored in args[0].
Note: we overload the main method and can have any number of main methods of
other signatures, but the JRE will automatically start the execution by calling only
the main method which is having the above discussed signature. If the JRE doesnt
find any such main method, then itll raise an appropriate exception. Its not a good
idea to have the main method overloaded.
//Illegal modifier for the class classTest; only public, abstract & final are
permitted
Class Loader
In a Java Virtual Machine (JVM), each and every class is loaded by some instance
of a java.lang.ClassLoader. The ClassLoader class is located in the java.lang
package and we can extend it to add our own functionality to class loading.
When a new JVM is started by java HelloWorld, the bootstrap class loader is
responsible for loading key java classes like java.lang.Object and other runtime
code into memory. The runtime classes are packaged inside jre/lib/rt.jar file. We
cannot find the details of the bootstrap class loader in the java language
specification, since this is a native implementation. For this reason the behavior
of the bootstrap class loader will differ across JVM.
Bootstrap
isn't
the
only
class
loader.
For
starters,
JVM
defines
an extension class loader for loading classes from standard Java extension APIs,
and a system class loader for loading classes from the general class path
(including your application classes).
Applications can also define their own class loaders for special purposes (such as
run-time reloading of classes). Such added class loaders are derived from
thejava.lang.ClassLoader class (possibly indirectly), which provides the core
support for building an internal class representation (ajava.lang.Class instance)
from an array of bytes. Each constructed class is in some sense "owned" by the
class loader that loaded it. Class loaders normally keep a map of the classes
they've loaded, to be able to find one by name if it's requested again.
Each class loader also keeps a reference to a parent class loader, defining a tree
of class loaders with the bootstrap loader at the root. When an instance of a
particular class (identified by name) is needed, whichever class loader initially
handles the request normally checks with its parent class loader first before
trying to load the class directly.
This applies recursively if there are multiple layers of class loaders, so it means
that a class will normally be visible not only within the class loader that loaded it,
but also to all descendant class loaders. It also means that if a class can be
loaded by more than one class loader in a chain, the one furthest up the tree will
be the one that actually loads it.
There are many circumstances where multiple application classloaders are used
by Java programs. One example is within the J2EE framework. Each J2EE
application loaded by the framework needs to have a separate class loader to
prevent classes in one application from interfering with other applications. The
framework code itself will also use one or more other class loaders, again to
prevent interference to or from applications.
Trees of loaders
As an example of a class loader hierarchy in action, Figure 1 shows the class loader
hierarchy defined by the Tomcat servlet engine. Here the Common class loader
loads from JAR files in a particular directory of the Tomcat installation that's
intended for code shared between the server and all Web applications. The Catalina
loader is for Tomcat's own classes, and the Shared loader for classes shared
between Web applications. Finally, each Web application gets its own loader for its
private classes.
In this type of environment, keeping track of the proper loader to use for requesting
a new class can be messy. Because of this,
thesetContextClassLoader and getContextClassLoader methods were added to
the java.lang.Thread class in the Java 2 platform. These methods let the framework
set the class loader to be used for each application while running code from that
application.
The flexibility of being able to load independent sets of classes is an important
feature of the Java platform. Useful as this feature is, though, it can create confusion
in some cases. One confusing aspect is the continuing issue of dealing with JVM
classpaths. In the Tomcat hierarchy of class loaders shown in Figure 1, for instance,
classes loaded by the Common class loader will never be able to directly access (by
name) classes loaded by a Web application. The only way to tie these together is
through the use of interfaces visible to both sets of classes. In this case, that
includes the javax.servlet.Servlet implemented by Java servlets.
Problems can arise when code is moved between class loaders for any reason. For
instance, when J2SE 1.4 moved the JAXP API for XML processing into the standard
distribution, it created problems for many environments where applications had
previously relied on loading their own chosen implementations of the XML APIs. With
J2SE 1.3, this can be done just by including the appropriate JAR file in the user class
path. In J2SE 1.4, the standard versions of these APIs are now in the extensions
class path, so these will normally override any implementations present in the user
class path.
Other types of confusion are also possible when using multiple class loaders. Figure
2 shows an example of a class identity crisis that results when an interface and
associated implementation are each loaded by two separate class loaders. Even
though the names and binary implementations of the interfaces and classes are the
same, an instance of the class from one loader cannot be recognized as
implementing the interface from the other loader. This confusion could be resolved
in Figure 2 by moving the interface class I into the System class loader's space.
There would still be two separate instances of class A, but both would implement
the same interface I.
Figure 2. Class identity crisis
If you are familiar with DOS operating system and how to use command prompt in Windows or shell in
Linux setting PATH and CLASSPATH is trivial exercise. Both PATH and CLASSPATH are environment
variable and can be set using export in Linux and using set keyword in DOS and Windows as shown
below:
Command to set PATH in Windows
set PATH=%PATH%;C:\Program Files\Java\JDK1.6.20\bin
Command to set PATH in UNIX/Linux
export PATH = ${PATH}:/opt/Java/JDK1.6.18/bin
Look at the difference between two commands, in Linux use colon(:) as separator and in Windows use
semi-colon(;) as separator.
Command to set CLASSPATH in windows
set CLASSPATH=%CLASSPATH%;C:\Program Files\Java\JDK1.6.20\lib
When programing in Java, you make other classes available to the class you are writing by putting
something like this at the top of your source file:
import org.javaguy.coolframework.MyClass
or sometimes you 'bulk import' stuff by saying:
import org.javaguy.coolframework.*
so later in your program when you say:
mine = MyClass.new();
the java virtual machine can know to load your compiled class.
It would be impractical to have the VM look through every folder on your machine, so you have to
provide the VM a list of places to look. This is done by putting folder and jar files on your classpath.
Before we talk about how the classpath is set, lets talk about .class files, packages, and .jar files.
First, let suppose that MyClass is something you built as part of your project, and it is in a directory
in your project called 'output'. The .class file would be at
'output/org/javaguy/coolframework/MyClass.class' (along with every other file in that package). in
order to get to that file, your path would simply need to contain the folder 'output'... not the whole
package structure, since your import statement provides all that information to the VM.
Now lets suppose that you bundle CoolFramework up into a .jar file, and put that CoolFramework.jar
into a lib directory in your project. you would now need to put 'lib/CoolFramework.jar' into your
classpath... the VM will look inside th jar file for the 'org/javaguy/coolpackage' part, and find your
class.
So, classpaths contain:
on a windows machine you have to go to your environment settings and either add or modify the
value that s already there.
The second way is to use the -cp parameter when starting Java, like this:
java -cp
"/home/myaccount/myproject/lib/CoolFramework.jar:/home/myaccount/myproject/output
/" MyMainClass
A variant on this third way is often done with a .sh or .bat file that calculates the classpath and
passes it to java via the -cp parameter.
So whats the best way to do it?
Setting stuff globally via environment variables is bad... generally for the same kinds of reasons that
global variables are bad. You change the CLASSPATH environment variable so one program works,
and you end up breaking another program.
The -cp is the way to go... I generally make sure my CLASSPATH environment variable is an empty
string where I develop, whenever possible, so that I avoid global classpath issues (some tools aren't
happy when the global classpath is empty though - I know of two common, mega-thousand dollar
licensed J2EE and Java servers that have this kind of issue with their command-line tools).