Bca Java Programming Unit-2
Bca Java Programming Unit-2
Garbage Collection is a key feature of the Java programming language that automatically manages memory
allocation and deallocation for objects that are created in an eden space.
Garbage Collection in Java allows developers to focus on writing code without worrying about memory
management, making Java a popular choice for building complex and large-scale applications. However,
understanding how Garbage Collection works is essential for Java developers to optimize their code's
performance and avoid common memory-related errors.
OutofMemoryErrors
OutofMemoryError is a type of error that occurs when a program or application attempts to allocate more
memory than the available amount. This error occurs when the Java Virtual Machine (JVM) or another platform
runs out of memory while trying to run an application.
An OutofMemoryError typically occurs when an application or program tries to create new objects, but the
JVM is unable to allocate memory to accommodate them. This error can also occur when an application is using
too much memory and is not releasing it properly.
When an OutofMemoryError occurs, the application will usually crash and terminate. This error is common in
programs that deal with large amounts of metadata, such as an image or video processing applications, or
programs that handle large databases.
To resolve this error, you may need to increase the amount of memory available to the application or optimize
the application's memory usage. This can be done by modifying the JVM parameters or by using a memory
profiler tool to identify memory leaks or inefficient memory usage.
Overall, Java's garbage collection provides many benefits that make it a valuable tool for developers. Here are
some benefits of using Java's garbage collection:
Developers benefit from Java garbage collection’s ability to automatically manage memory, prevent memory
leaks, enable dynamic memory allocation, improve performance, and optimize memory usage, garbage
collection can help developers write better, more efficient programs.
What events trigger Java garbage collection?
In Java, garbage collection is triggered automatically by the JVM (Java Virtual Machine) when it determines
that the heap is getting full or when a certain amount of time has passed.
There are several events that can trigger garbage collection in Java:
● Heap space allocation: When the JVM needs to allocate memory for a new object, and there is not
enough space in the heap, it triggers garbage collection to reclaim unused memory or store them in the
survivor space.
● System.gc() method call: You can explicitly request garbage collection by calling the System.gc()
method, although there is no guarantee that it will run.
● Old generation threshold: Garbage collection can also be triggered when the heap size of the old
generation heap space (which stores long-lived objects) reaches a certain threshold.
● PermGen/Metaspace threshold: In Java versions before Java 8, garbage collection can also be
triggered when the size of the PermGen (Permanent Generation) or Metaspace (in Java 8 and later)
memory areas reaches a certain threshold.
● Time-based: Sometimes, garbage collection can be triggered based on a time interval. For example, the
JVM might trigger garbage collection every hour or every day, regardless of memory usage.
It's worth noting that the exact behavior of garbage collection in Java can vary depending on the JVM
implementation and configuration.
How to request JVM to run Garbage Collector
To request the Java Virtual Machine (JVM) to run garbage collector, you can follow these steps:
1. Call the System.gc() method: This method is used to request the JVM to run the garbage collector. It is
not guaranteed that the garbage collector will run immediately after this method is called.
2. Use the Runtime.getRuntime().gc() method: This method is similar to the System.gc() method, but it
is less likely to be overridden by the JVM implementation.
3. Use the -XX:+DisableExplicitGC JVM flag: This flag disables explicit garbage collection requests.
This means that even if you call System.gc() or Runtime.getRuntime().gc(), the garbage collector will
not be triggered.
It's important to note that explicitly requesting the garbage collector to run is generally not recommended, as the
JVM is designed to automatically manage memory allocation and garbage collection. Explicit garbage
collection requests can sometimes have a negative impact on performance.
What garbage collectors are available for Java?
Each garbage collector has its own strengths and weaknesses, and the choice of which collector to use depends
on the specific needs of the application. It is also possible to configure and tune the garbage collector settings to
optimize performance for a particular application.
Method Overriding
Overriding in Java occurs when a subclass implements a method which is already defined in
the superclass or Base Class. The method in the subclass must have the same signature as in
the superclass.
Method overriding is a key concept in Java that enables Run-time polymorphism. It allows a
subclass to provide its specific implementation for a method inherited from its parent class.
The actual method executed is determined by the object’s runtime type, not just the reference
variable’s type.
1) An overriding method’s access modifier in a subclass can be more permissive (e.g.,
protected to the public) than the overridden method in the superclass. However,
reducing the access level (e.g., making a protected method private) is not allowed and
will result in a compile-time error.
2) Final methods cannot be override.
3) Private methods cannot be overridden as they are bonded during compile time.
4) Method must have the same return type (or subtype)
5) Static methods cannot be override(Method Hiding)
When an error occurs within a method, the method creates an object and hands it
off to the runtime system. The object, called an exception object, contains
information about the error, including its type and the state of the program when
the error occurred. Creating an exception object and handing it to the runtime
system is called throwing an exception.
The runtime system searches the call stack for a method that contains a block of
code that can handle the exception. This block of code is called an exception
handler. The search begins with the method in which the error occurred and
proceeds through the call stack in the reverse order in which the methods were
called. When an appropriate handler is found, the runtime system passes the
exception to the handler. An exception handler is considered appropriate if the
type of the exception object thrown matches the type that can be handled by the
handler.
The exception handler chosen is said to catch the exception. If the runtime
system exhaustively searches all the methods on the call stack without finding an
appropriate exception handler, as shown in the next figure, the runtime system
(and, consequently, the program) terminates.
Searching the call stack for the exception handler.
1)The first kind of exception is the checked exception. These are exceptional
conditions that a well-written application should anticipate and recover
from. For example, suppose an application prompts a user for an input file
name, then opens the file by passing the name to the constructor
for java.io.FileReader. Normally, the user provides the name of an existing,
readable file, so the construction of the FileReader object succeeds, and the
execution of the application proceeds normally. But sometimes the user
supplies the name of a nonexistent file, and the constructor
throws java.io.FileNotFoundException. A well-written program will catch
this exception and notify the user of the mistake, possibly prompting for a
corrected file name.Checked exceptions are subject to the Catch or Specify
Requirement. All exceptions are checked exceptions, except for those
indicated by Error, RuntimeException, and their subclasses.
2)The second kind of exception is the error. These are exceptional conditions
that are external to the application, and that the application usually cannot
anticipate or recover from. For example, suppose that an application
successfully opens a file for input, but is unable to read the file because of a
hardware or system malfunction. The unsuccessful read will
throw java.io.IOError. An application might choose to catch this exception,
in order to notify the user of the problem — but it also might make sense
for the program to print a stack trace and exit.Errors are not subject to the
Catch or Specify Requirement. Errors are those exceptions indicated
by Error and its subclasses.
3)The third kind of exception is the runtime exception. These are exceptional
conditions that are internal to the application, and that the application
usually cannot anticipate or recover from. These usually indicate
programming bugs, such as logic errors or improper use of an API. For
example, consider the application described previously that passes a file
name to the constructor for FileReader. If a logic error causes a null to be
passed to the constructor, the constructor will throw NullPointerException.
The application can catch this exception, but it probably makes more sense
to eliminate the bug that caused the exception to occur.Runtime
exceptions are not subject to the Catch or Specify Requirement. Runtime
exceptions are those indicated by RuntimeException and its
subclasses.Errors and runtime exceptions are collectively known
as unchecked exceptions.
Hierarchy of the Throwable class
Three exception handler components — the try, catch, throw,throws and finally
}
Each catch block is an exception handler that handles the type of exception
indicated by its argument. The argument type, ExceptionType, declares the type
of exception that the handler can handle and must be the name of a class that
inherits from the Throwable class. The handler can refer to the exception
with name.
The catch block contains code that is executed if and when the exception handler
is invoked. The runtime system invokes the exception handler when the handler
is the first one in the call stack whose ExceptionType matches the type of the
exception thrown. The system considers it a match if the thrown object can
legally be assigned to the exception handler's argument.
} catch (IOException e) {
throw new SampleException("Other IOException", e);
}
In this example, when an IOException is caught, a
new SampleException exception is created with the original cause attached and
the chain of exceptions is thrown up to the next higher level exception handler.
Stack Trace
Definition: A stack trace provides information on the execution history of the
current thread and lists the names of the classes and methods that were called at
the point when the exception occurred. A stack trace is a useful debugging tool
that you'll normally take advantage of when an exception has been thrown.
The following code shows how to call the getStackTrace method on the
exception object.
catch (Exception cause) {
StackTraceElement elements[] = cause.getStackTrace();
for (int i = 0, n = elements.length; i < n; i++) {
System.err.println(elements[i].getFileName()
+ ":" + elements[i].getLineNumber()
+ ">> "
+ elements[i].getMethodName() + "()");
}
}
Logging API
The next code snippet logs where an exception occurred from within
the catch block. However, rather than manually parsing the stack trace and
sending the output to System.err(), it sends the output to a file using the logging
facility in the java.util.logging package.
try {
Handler handler = new FileHandler("OutFile.log");
Logger.getLogger("").addHandler(handler);
} catch (IOException e) {
Logger logger = Logger.getLogger("package.name");
StackTraceElement elements[] = e.getStackTrace();
for (int i = 0, n = elements.length; i < n; i++) {
logger.log(Level.WARNING, elements[i].getMethodName());
}
}
Java Errors vs Exceptions
According to the official documentation, an error “indicates serious problems
that a reasonable application should not try to catch.” This refers to problems that
the application can not recover from - they should be dealt with by modifying
application architecture or by refactoring code.
Here is an example of a method that throws a error, which is not handled in code:
public static void print(String myString) {
print(myString);
}
In this example, the recursive method “print” calls itself over and over again until
it reaches the maximum size of the Java thread stack, at which point it exits with
a StackOverflowError:
Exceptions that can occur at compile-time are called checked exceptions since
they need to be explicitly checked and handled in code. Classes that directly
inherit Throwable - except RuntimeException and Error - are checked exceptions
e.g. IOException, InterruptedException etc.
In this example, both statements within the try block (the instantiation of
the BufferedWriter object and writing to file using the object) can
throw IOException, which is a checked exception and therefore needs to be
handled either by the method or its caller. In the example, IOException is
handled within the method and the exception stack trace is printed to the console.
While checked exceptions force explicit handling, this doesn't necessarily lead to
better code. In fact, many modern Java frameworks and libraries prefer
unchecked exceptions for their cleaner API design. The Spring framework, for
instance, translates checked exceptions into unchecked ones to avoid cluttering
method signatures.
Unchecked Exceptions
Unchecked exceptions can be thrown "at any time" (i.e. run-time). Therefore,
methods don't have to explicitly catch or throw unchecked exceptions. Classes
that inherit RuntimeException are unchecked exceptions
e.g. ArithmeticException, NullPointerException.
Throwable class
public class Throwable
extends Object
implements Serializable
The Throwable class is the superclass of all errors and exceptions in the Java
language. Only objects that are instances of this class (or one of its subclasses)
are thrown by the Java Virtual Machine or can be thrown by the
Java throw statement.
Constructor Summary
Throwable()
Constructs a new throwable with null as its detail message.
Throwable(String message)
Constructs a new throwable with the specified detail message.
Throwable(Throwable cause)
Constructs a new throwable with the specified cause and a detail message
of (cause==null ? null : cause.toString()) (which typically contains the class and
detail message of cause).
Method Summary
Throwable fillInStackTrace()
Fills in the execution stack trace.
Throwable getCause()
Returns the cause of this throwable or null if the
cause is nonexistent or unknown.
String getLocalizedMessage()
Creates a localized description of this throwable.
String getMessage()
Returns the detail message string of this throwable.
StackTraceElement[] getStackTrace()
Provides programmatic access to the stack trace
information printed by printStackTrace().
void printStackTrace()
Prints this throwable and its backtrace to the
standard error stream.
String toString()
Returns a short description of this throwable.
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
Instances of two subclasses, Error and Exception, are conventionally used to
indicate that exceptional situations have occurred.
Error class
java.lang.Object
java.lang.Throwable
java.lang.Error
Constructor Summary
Error()
Constructs a new error with null as its detail message.
Error(String message)
Constructs a new error with the specified detail message.
Error(Throwable cause)
Constructs a new error with the specified cause and a detail message
of (cause==null ? null : cause.toString()) (which typically contains the class and
detail message of cause).
Method Summary
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
Exception class
java.lang.Object
java.lang.Throwable
java.lang.Exception
Constructor Summary
Exception()
Constructs a new exception with null as its detail message.
Exception(String message)
Constructs a new exception with the specified detail message.
Exception(Throwable cause)
Constructs a new exception with the specified cause and a detail message
of (cause==null ? null : cause.toString()) (which typically contains the class and
detail message of cause).