Tuesday, September 30, 2008

Some notes for JSF

The three points that we discussed were:

1. Mutliple render kits:

Now a days there are many devices that are web enabled. So application developers have challenge to develop components that can work across various platforms. For example, if we have an application that works on standard web browser and we want to extend it to make it enable to work on a WAP device. So, to handle this case we need components to be rendered in more than one way. Here JSF can help you . It is a simple task for JSF. Solution is to develop separate renderers for the component. JSF components use different renderers depending on the device used.

Render kit can target a specific device like phone, PC or markup language like HTML,WML, SVG. This is one of the best benefit of JSF because JSF doesn't limit to any device or markup.

2. Controller Flexibility/Event Handling

JSF is a component/event oriented approach, and Struts is an action oriented approach.

One of the major goals of Struts was to implement a framework that utilized Sun's Model 2 framework and reduced the common and often repetitive tasks in Servlet and JSP development. The heart of Struts is the Controller. Struts uses the Front Controller Pattern and Command Pattern. A single servlet takes a request, translates HTTP parameters into a Java ActionForm, and passes the ActionForm into a Struts Action class, which is a command. The URI denotes which Action class to go to. The Struts framework has one single event handler for the HTTP request. Once the request is met, the Action returns the result back to the front controller, which then uses it to choose where to navigate next.
JSF uses the Page Controller Pattern. Although there is a single servlet every faces request goes through, the job of the servlet is to receive a faces page with components. It will then fire off events for each component and render the components using a render toolkit. The components can also be bound to data from the model. JSF is the winner in this area, because it adds many benefits of a front controller, but at the same time gives you the flexibility of the Page Controller.

JSF can have several event handlers on a page while Struts is geared to one event per request. In addition, with Struts, your ActionForms have to extend Struts classes, creating another layer of tedious coding or bad design by forcing your model to be ActionForms. JSF, on the other hand, gives developers the ability to hook into the model without breaking layering.

3. JSF Component Tree
The user interface can be by nature hierarchical, and we can structure the code to reflect that. For very dynamic parts of the user interface, programmatic manipulation is useful. But, this is certainly the uncommon case. Most user interfaces are extremely static except at the level of individual controls. JSF helps you even in this uncommon case, since it lets you directly manipulate the JSF component tree in Java code. And of course, you can always fall back to writing JavaScript code that works with the browser's DOM.

Message from my java group...it would be much helpful in understanding on this topic

Struts a bit excessive and using it was like trying to fit a square peg in a round hole.

In Struts 1.x, you can only have String objects in ActionForms. Whereas, in JSF, you
can even have Date, BigDecimal, Integer, etc. in the ManagedBeans.

The JSF ManagedBeans are a combination of Struts ActionForm and Action both rolled into one. Again, in Struts Action, only the execute method is ever exposed. Whereas, in JSF, you can have any method being called by the front-end.

But thats not all. Validation is a big pain in Struts. It is tucked away in validation.xml or in some cases, in ActionForm or Action. Whereas, in JSF, you can have validation and conversion at front-end.

With all this going on, you might think that this is the best solution.

However, the trouble here is you still have the attributes being duplicated in your ManagedBeans and again in the Entities that you will persist.

For example, if you have a users table, you will end up having a Java Class Users for storing database entity and a Java Class UsersBean to use as your ManagedBean. And then just like the Struts days, where you write code to take ActionForm values and store them to the Entity before saving to database and vice versa when reading them from database, you will do same conversion from ManagedBean to Entity and
back in JSF.

In brief, the comparison as as follows:

Struts:

1. JSP with Struts tags
2. Configuration in struts-config. xml
3. Flow controlled by ActionServlet
4. Validation in validation.xml
5. Available for free
6. Only Apache implementation
7. No components available

JSF:

1. JSP with JSF tags
2. Configuration in faces-config. xml
3. Flow controlled by FacesServlet
4. Validation in the front-end
5. Available for free
6. Implementations - Apache MyFaces, Sun Reference Implementation
(recommended one for now)
7. Components available from RichFaces, IceFaces, AJAX4JSF and many
more

Now, just a small introduction to what Seam does here.

With JSF or Struts, you need beans on the front-end (ManagedBean or ActionForm) to hold front-end values and beans on the back-end to hold back-end values. And then you have to write plumbing code to transfer values back and forward between front-end and back-end beans.

Seam collapses the need for all this and allows you to expose entities directly onto the front-end.

It also makes use of Hibernate Annotations such as not-null for required fields and length to check for max-length of input fields.

If you are interested, I can post an article on a brief introduction to Seam and getting started with it. Must warn you a bit though that you do need about a month or so to get to grips with Seam like any other application such as Struts, Spring or Hibernate.

Wednesday, September 24, 2008

General Spring related

1. What is IOC? is it opposite of OOP?
2. what is pico,micro and spring container?
3. what is JDK Proxy?
4. what is main use of AOP?
5. what is jdk proxy?
6. what is convetion over configuration?
7. what is EH cache?
8. does remote transaction support in Spring?

http://java.sys-con.com/node/286882

First Web Services Client

good article--
http://seekda.com/blog/write-your-first-web-services-client-%E2%80%93-part-1-finding-and-testing-services/

REST web services

Representational State Transfer (popularly known as REST) is a popular architectural
style of building web services. It doesn’t depend on a SOAP envelope, but it
does leverage XML and the HTTP protocol. Statistics revealed by large web-based
companies like Amazon and Yahoo! shows that a majority of their consumers use a
REST interface.
Unfortunately, Java EE 5 doesn’t require support for REST web services and each
vendor supports its own approach. GlassFish supports RESTful web services by creating
an implementation of the javax.ws.Provider interface. Vendors such as
Oracle allow you to convert a Java object into a web service by using proprietary configuration
or a proprietary annotation. Check your vendor’s documentation to see if
they provide REST support, and see how that support is implemented. For more
information on REST, hop over to http://en.wikipedia.org/wiki/Representational_
State_Transfer.

Monday, September 22, 2008

Business Process Execution Language

BPEL (Business Process Execution Language) is one of the new buzzwords thrown around with the same frequency as SOA (Service Oriented Architecture). Let us make an attempt to dismantle this jargon and try and understand the context and usage of this term.
BPEL talks about business processes. Hence, we first need to take a look at this term. It actually means what we think about this term. It is some work that we need to carry out (e.g. transfer money between two accounts, or purchase goods, or generate invoice). Usually, it is composed of a sequence of steps or actions in a specific order. When all the steps are completed successfully, the business process is considered to be complete and successful as as whole. A business process is rarely all-automated, and is usually a mixture of automated steps plus human interventions. Also, it can involve interactions with various other applications/systems inside the organization, or even outside. Hence, usually some sort of integration-related requirements are a part of any business process.

Now, what if we can describe a business processes in a language of its own? Better yet, what if we can implement it as a service (usually a Web service)? That is where we start moving from a business process to BPEL. If we can create a service that spans across all the steps necessary to complete the objectives of the business process, we would provide the technology support for implementing this as well. Hence, we can consider BPEL as a language that allows us to combine multiple small services (called as fine-grained services in the jargon) to create a big service that implements our business process (called as coarse-grained service in the jargon), in the right sequence.

BPEL, like anything else, these days, is based on XML. It is a part of the Web Services specifications. It allows us to define, carry out (i.e. orchestrate in the jargon), and manage business processes. The business processes themselves, as mentioned earlier, are implemented as Web services in the most common form. Therefore, we can crudely define BPEL also as a language that arranges one Web service after the other in a well-defined sequence, and gets some useful work done out from it (which we call as a business process).

The whole idea here is that non-technical people should be able to create and describe business processes. For taking the idea further, most BPEL development environments provide intuitive IDEs that are almost completely GUI-driven. This means that business analysts can not only elicit and describe requirements in plain English, but then can actually draw the flow of events as it is supposed to happen (e.g. Receive account numbers and amount -> Validate accounts -> Perform funds transfer -> On success, return ‘Success’ message, but on failure, return ‘Error’ message) using ready-made icons. Then how is this different from the use cases and sequence diagrams in UML? Well, the idea is quite similar in concept. However, the difference is that BPEL is closely tied to the SOA/Web services buzz (instead of the object orientation buzz), and secondly BPEL diagrams generate code in XML-like syntax (unlike the Java/C++ syntax as in the case of UML).

Thursday, September 18, 2008

All about JAAS

All about JAAS

Have you ever needed to create a login authentication mechanism for an application? Odds are, you have, and probably more than once, with each new implementation being close, but not identical, to the previous one. For example, one implementation might use an Oracle database, another might use an NT authentication, and another, an LDAP (lightweight access directory protocol) directory. Wouldn't it be nice to support all these security mechanisms without changing any application-level code?
Now in the Java world, you can with the Java Authentication and Authorization Service (JAAS). This relatively new API was an extension in J2SE (Java 2 Platform, Standard Edition) 1.3, is a core API in J2SE 1.4, and is also part of the J2EE (Java 2 Platform, Enterprise Edition) 1.3 specification.

Developing secure web applications

BASIC CONCEPTS
1. Authentication: Authentication is the process of identifying a person or even a system, such as an application and validating their credentials.
2. Authorization: Authorization is the process of determining whether a user is permitted to access a particular resource that she has requested.
3. Data integrity: Data integrity is the process of ensuring that the data is not tampered with while in transit from the sender to the receiver.
4. Confidentiality or data privacy: Confidentiality is the process of ensuring that no one except the intended user is able to access sensitive information. The difference between authorization and confidentiality is in the way the information is protected. Authorization prevents the information from reaching unintended parties in the first place, while confidentiality ensures that even if the information falls into the wrong hands, it remains unusable

5. Auditing: Auditing is the process of recording security-related events taking place in the system in order to be able to hold users accountable for their actions.

6. Malicious code: A piece of code that is meant to cause harm to computer systems is called malicious code. This includes viruses, worms, and Trojan horses.

7. Web site attacks: A web site may be attacked by different people for different reasons. For example, a hacker may attack for pleasure, a terminated employee may attack for revenge, or a professional thief may attack for the purpose of stealing credit card numbers.
Broadly, there are three types of web site attacks:
• Secrecy attacks—Attempts to steal confidential information by sniffing the communications between two machines. Encrypting the data being transmitted can prevent such attacks.
• Integrity attacks—Attempts to alter information in transit with malicious intent. If these attempts succeed, it will compromise the data integrity. IP spoofing is one of the common techniques used in integrity attacks. In this technique, the intruder sends messages to a server with an IP address indicating that the message is coming from a trusted machine. The server is thus fooled into giving access to the intruder. Such attacks can be prevented by using strong authentication techniques, such as public-key cryptography.
• Denial-of-service attacks (or availability attacks)—Attempts to flood a system with fake requests so that the system remains unavailable for legitimate requests. Creating network congestion by sending spurious data packets also comes under this category. Such attacks can be prevented by using firewalls that block network traffic on unintended ports.

Wednesday, September 17, 2008

What is String literal pool and use of String.intern method?

How to create a String


There are two ways to create a String object in Java:

Using the new operator. For example,
String str = new String("Hello");.
Using a string literal or constant expression). For example,
String str="Hello"; (string literal) or
String str="Hel" + "lo"; (string constant expression).
What is difference between these String's creations? In Java, the equals method can be considered to perform a deep comparison of the value of an object, whereas the == operator performs a shallow comparison. The equals method compares the content of two objects rather than two objects' references. The == operator with reference types (i.e., Objects) evaluates as true if the references are identical - point to the same object. With value types (i.e., primitives) it evaluates as true if the value is identical. The equals method is to return true if two objects have identical content - however, the equals method in the java.lang.Object class - the default equals method if a class does not override it - returns true only if both references point to the same object.

Let's use the following example to see what difference between these creations of string:

public class DemoStringCreation {

public static void main (String args[]) {
String str1 = "Hello";
String str2 = "Hello";
System.out.println("str1 and str2 are created by using string literal.");
System.out.println(" str1 == str2 is " + (str1 == str2));
System.out.println(" str1.equals(str2) is " + str1.equals(str2));


String str3 = new String("Hello");
String str4 = new String("Hello");
System.out.println("str3 and str4 are created by using new operator.");
System.out.println(" str3 == str4 is " + (str3 == str4));
System.out.println(" str3.equals(str4) is " + str3.equals(str4));

String str5 = "Hel"+ "lo";
String str6 = "He" + "llo";
System.out.println("str5 and str6 are created by using string constant expression.");
System.out.println(" str5 == str6 is " + (str5 == str6));
System.out.println(" str5.equals(str6) is " + str5.equals(str6));

String s = "lo";
String str7 = "Hel"+ s;
String str8 = "He" + "llo";
System.out.println("str7 is computed at runtime.");
System.out.println("str8 is created by using string constant expression.");
System.out.println(" str7 == str8 is " + (str7 == str8));
System.out.println(" str7.equals(str8) is " + str7.equals(str8));

}
}

The output result is:

str1 and str2 are created by using string literal.
str1 == str2 is true
str1.equals(str2) is true
str3 and str4 are created by using new operator.
str3 == str4 is false
str3.equals(str4) is true
str5 and str6 are created by using string constant expression.
str5 == str6 is true
str5.equals(str6) is true
str7 is computed at runtime.
str8 is created by using string constant expression.
str7 == str8 is false
str7.equals(str8) is true

The creation of two strings with the same sequence of letters without the use of the new keyword will create pointers to the same String in the Java String literal pool. The String literal pool is a way Java conserves resources.



String Literal Pool
String allocation, like all object allocation, proves costly in both time and memory. The JVM performs some trickery while instantiating string literals to increase performance and decrease memory overhead. To cut down the number of String objects created in the JVM, the String class keeps a pool of strings. Each time your code create a string literal, the JVM checks the string literal pool first. If the string already exists in the pool, a reference to the pooled instance returns. If the string does not exist in the pool, a new String object instantiates, then is placed in the pool. Java can make this optimization since strings are immutable and can be shared without fear of data corruption. For example

public class Program
{
public static void main(String[] args)
{
String str1 = "Hello";
String str2 = "Hello";
System.out.print(str1 == str2);
}
}

The result is

true



Unfortunately, when you use

String a=new String("Hello");

a String object is created out of the String literal pool, even if an equal string already exists in the pool. Considering all that, avoid new String unless you specifically know that you need it! For example

public class Program
{
public static void main(String[] args)
{
String str1 = "Hello";
String str2 = new String("Hello");
System.out.print(str1 == str2 + " ");
System.out.print(str1.equals(str2));
}
}

The result is

false true



A JVM has a string pool where it keeps at most one object of any String. String literals always refer to an object in the string pool. String objects created with the new operator do not refer to objects in the string pool but can be made to using String's intern() method. The java.lang.String.intern() returns an interned String, that is, one that has an entry in the global String pool. If the String is not already in the global String pool, then it will be added. For example

public class Program
{
public static void main(String[] args)
{
// Create three strings in three different ways.
String s1 = "Hello";
String s2 = new StringBuffer("He").append("llo").toString();
String s3 = s2.intern();

// Determine which strings are equivalent using the ==
// operator
System.out.println("s1 == s2? " + (s1 == s2));
System.out.println("s1 == s3? " + (s1 == s3));
}
}

The output is

s1 == s2? false
s1 == s3? true

There is a table always maintaining a single reference to each unique String object in the global string literal pool ever created by an instance of the runtime in order to optimize space. That means that they always have a reference to String objects in string literal pool, therefore, the string objects in the string literal pool not eligible for garbage collection.



String Literals in the Java Language Specification Third Edition


Each string literal is a reference to an instance of class String. String objects have a constant value. String literals-or, more generally, strings that are the values of constant expressions-are "interned" so as to share unique instances, using the method String.intern.

Thus, the test program consisting of the compilation unit:

package testPackage;
class Test {
public static void main(String[] args) {
String hello = "Hello", lo = "lo";
System.out.print((hello == "Hello") + " ");
System.out.print((Other.hello == hello) + " ");
System.out.print((other.Other.hello == hello) + " ");
System.out.print((hello == ("Hel"+"lo")) + " ");
System.out.print((hello == ("Hel"+lo)) + " ");
System.out.println(hello == ("Hel"+lo).intern());
}
}
class Other { static String hello = "Hello"; }

and the compilation unit:

package other;
public class Other { static String hello = "Hello"; }

produces the output:

true true true true false true

This example illustrates six points:

Literal strings within the same class in the same package represent references to the same String object.
Literal strings within different classes in the same package represent references to the same String object.
Literal strings within different classes in different packages likewise represent references to the same String object.
Strings computed by constant expressions are computed at compile time and then treated as if they were literals.
Strings computed by concatenation at run time are newly created and therefore distinct.
The result of explicitly interning a computed string is the same string as any pre-existing literal string with the same contents.

Tuesday, September 16, 2008

Add Logging at Class Load Time with Java Instrumentation

Add Logging at Class Load Time with Java Instrumentation
See: http://java.sun.com/javase/6/docs/api/java/lang/instrument/package-summary.html
When you're trying to analyze why a program failed, a very valuable piece of information is what the program was actually doing when it failed. In many cases, this can be determined with a stack trace, but frequently that information is not available, or perhaps what you need is information about the data that was being processed at the time of failure.
Traditionally this means using a logging framework like log4j or the Java Logging API, and then writing and maintaining all necessary log statements manually. This is very tedious and error-prone, and well-suited for automation. Java 5 added the Java Instrumentation mechanism, which allows you to provide "Java agents" that can inspect and modify the byte code of the classes as they are loaded.
This article will show how to implement such a Java agent, which transparently will add entry and exit logging to all methods in all your classes with the standard Java Logging API. The example used is Hello World:public class HelloWorld {
public static void main(String args[]) {
System.out.println("Hello World");
}
}
And here is the same program with entry and exit log statements added:import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
public class LoggingHelloWorld {
final static Logger _log = Logger.getLogger(LoggingHelloWorld.class.getName());
public static void main(String args[]) {
if (_log.isLoggable(Level.INFO)) {
_log.info("> main(args=" + Arrays.asList(args) + ")");
}
System.out.println("Hello World");
if (_log.isLoggable(Level.INFO)) {
_log.info("<> main(args=[])
Hello World
2007-12-22 22:08:52 LoggingHelloWorld main
INFO: < title="blocked::http://today.java.net/pub/a/today/2008/04/24/add-logging-at-class-load-time-with-instrumentation.html" href="http://today.java.net/pub/a/today/2008/04/24/add-logging-at-class-load-time-with-instrumentation.html">http://today.java.net/pub/a/today/2008/04/24/add-logging-at-class-load-time-with-instrumentation.html

shared jar files in ear packaging

Q: Where you will keep your shared jar files in ear packaging so that it should be accessible by EJB module or web application and others module in ear?
ANS: 1. Make lib folder in root of ear packaging and put all shared file into this folder. This is new convention in JAVA EE.
2. Manifest Class-Path entry of all jar or war file for all shared resources.

Any other thought?

Why wait and notify methods are in Object class

1. Why wait and notify methods are in Object class?
http://codeguru.earthweb.com/java/tij/tij0157.shtml#Heading499
One fairly unique aspect of wait( ) and notify( ) is that both methods are part of the base class Object and not part of Thread as are sleep( ), suspend( ), and resume( ). Although this seems a bit strange at first – to have something that’s exclusively for threading as part of the universal base class – it’s essential because they manipulate the lock that’s also part of every object. As a result, you can put a wait( ) inside any synchronized method, regardless of whether there’s any threading going on inside that particular class. In fact, the only place you can call wait( ) is within a synchronized method or block. If you call wait( ) or notify( ) within a method that’s not synchronized, the program will compile, but when you run it you’ll get an IllegalMonitorStateException with the somewhat non-intuitive message “current thread not owner.” Note that sleep( ), suspend( ), and resume( ) can all be called within non- synchronized methods since they don’t manipulate the lock.
You can call wait( ) or notify( ) only for your own lock. Again, you can compile code that tries to use the wrong lock, but it will produce the same IllegalMonitorStateException message as before. You can’t fool with someone else’s lock, but you can ask another object to perform an operation that manipulates its own lock. So one approach is to create a synchronized method that calls notify( ) for its own object. However, in Notifier you’ll see the notify( ) call inside a synchronized block:

In nutshell any Object can be the monitor for a thread. The wait and notify are called on the monitor. The running thread checks with the monitor. So the wait and notify methods are in Object and not Thread.


2. If we define "this=null" in method what will happen?

you can not do because this is final variable. this will give compile time error.


3. What is Garbage Collection and the finalize() Methodhttp://tutorials.beginners.co.uk/integrate_read/i/216/vs_p/p/p/3
Before an object is destroyed by the garbage collector, the object's finalize() method is called to allow it to perform any necessary cleanup tasks. For example, if the object had used native methods to obtain resources (allocate memory, create network connections, etc.), it might be necessary to release those resources explicitly before the object is destroyed.Just as you cannot be guaranteed that an object will ever be garbage collected, you cannot be certain that its finalize() method will be called. In Java 1.1, you could use the static runFinalizersOnExit() method in the java.lang.System class to force each object's finalize() method to be called prior to the termination of the JVM process. However, that method is deprecated in Java 2 because of problems that can occur when an object's finalize() method is invoked by one thread while another thread may be modifying the same object's state. In other words, runFinalizersOnExit() causes the finalize() method to be called for every object not previously finalized, even those that are still reachable.To illustrate the fact that it's not possible to predict when or if the garbage collector will run, we can make some minor modifications to the GarbageTest class defined earlier. Specifically, we'll override finalize() in GarbageTest and TestClass so that they'll issue messages before instances are garbage collected: public class GarbageTest {
protected Object objectRef;
public static void main(String[] args) {
GarbageTest gt = new GarbageTest();
System.out.println("Exiting main()");
}
public GarbageTest() {
objectRef = new TestClass(this);
}
protected void finalize() throws Throwable {
System.out.println("Finalizing GarbageTest");
}
class TestClass {
Object testref;
public TestClass(Object objref) {
testref = objref;
}
protected void finalize() throws Throwable {
System.out.println("Finalizing TestClass");
}
}
}
When this code is executed, neither finalize() method is called prior to termination of the JVM, so the only output produced is the message issued from the main() method as shown below: Exiting main()
However, the main() method can be modified to force the execution of the objects' finalize() methods prior to exit by using the deprecated runFinalizersOnExit() method as shown below: public static void main(String[] args) {
GarbageTest gt = new GarbageTest();
System.runFinalizersOnExit(true);
System.out.println("Exiting main()");
}
Executing this modified version of GarbageTest produces the following output, illustrating that the finalize() methods of both the GarbageTest and TestClass instances were called prior to termination of the JVM: Exiting main()
Finalizing TestClass
Finalizing GarbageTest
Ensuring that the finalize() methods are called without using the deprecated runFinalizersOnExit() method is slightly more complex, and as we'll see, depends upon the garbage collector implementation. For example, we can attempt to make this occur by making the GarbageTest instance unreachable while still executing the main() and then calling System.gc() as shown below: public static void main(String[] args) {
GarbageTest gt = new GarbageTest();
// System.runFinalizersOnExit(true);
gt = null;
System.gc();
System.out.println("Exiting main()");
}
Since the only reference to the GarbageTest instance is the local variable defined in the main() method, the following line makes that object unreachable: gt = null;
Since the object is unreachable, the call to System.gc() should cause the garbage collector to reclaim both the GarbageTest object and the TestClass instance to which it maintains a reference, and this is what happens with the "HotSpot" JVM in JDK 1.3 on Win32. However, if you execute this code using release 1.2.2 of JavaSoft's JVM for Win32 platforms, the following output is produced: Exiting main()
In other words, although both objects are unreachable, they are incorrectly ignored by the garbage collector, which occurs because the garbage collector in 1.2.2 is a partially accurate implementation. Its design makes it unable to identify some objects that are legitimate targets for collection, which can lead to memory leaks in your code. Interestingly enough, if you make the following minor change to the GarbageTest class and execute the modified version, the results will be different: public static void main(String[] args) {
createAndRelease();
System.gc();
System.out.println("Exiting main()");
}
private static void createAndRelease() {
GarbageTest gt = new GarbageTest();
gt = null;
}
Running this version of the GarbageTest program causes the garbage collector to correctly reclaim both the GarbageTest object and the TestClass instance to which it maintains a reference. The output produced by running the code is shown below: Finalizing GarbageTest
Finalizing TestClass
Exiting main()
Perhaps even more strangely, eliminating the second line (gt = null;) in the createAndRelease() method shown above causes the garbage collector to again fail to reclaim the two unreachable objects. These variations on the GarbageTest class and the different results that they produce illustrate the unreliability of partially accurate garbage collector algorithms. In a small application that runs for only a short length of time, such omissions may not be significant. However, for an application that is expected to continue running for a long time, the failure to reclaim unused heap space can become a serious problem and even cause the application to fail with an OutOfMemoryError.Fortunately, the HotSpot technology included in the JDK 1.3 JVM includes a fully accurate garbage collector. It will correctly reclaim the GarbageTest and TestClass objects with any of the implementations of the GarbageTest code described above: with or without the createAndRelease() method, and with or without assigning a null value to the gt variable.Reference ObjectsPrior to Java 2, object instances were garbage collected only when there were no more references to them from live threads. However, Java 2 includes classes that allow you to maintain special types of references to objects, and those new reference types will not prevent objects from being garbage collected.The classes are defined in the java.lang.ref package, and the Reference class is the superclass of the three new reference types: SoftReference, WeakReference, and PhantomReference. In addition to these classes, the ReferenceQueue class allows you to determine when references to an object have been cleared. References are normally cleared by the garbage collector when it prepares to reclaim an object, but you can explicitly clear a reference by calling the Reference object's clear() method.The traditional type of object reference provided in earlier releases of Java is referred to as a strong reference, and object instances with strong references cannot be garbage collected. The new reference types provide what are known collectively as weak references, which is somewhat confusing since the WeakReference class represents only one of these types. To create a weak reference to an object, you simply create an instance of the appropriate class, passing its constructor a reference to the object as shown below: // The myObject variable represents a strong reference
Object o = new Object();
// The softRef variable represents a soft reference
SoftReference softRef = new SoftReference(o);
// The weakRef variable represents a weak reference
WeakReference weakRef = new WeakReference(o);
// The phantomRef variable represents a phantom reference
// When creating a phantom reference, you must specify a reference
// queue (discussed later)
ReferenceQueue rq = new ReferenceQueue();
PhantomReference phantomRef = new PhantomReference(o, rg);
SoftReference and WeakReference instances can be used to create additional (possibly strong) references to the referenced object (also known as the referent) through the get() method. For example, the following code illustrates how a SoftReference is created, and is later used to create a strong reference to the referent: byte[] buffer = new byte[10000];
SoftReference bufferRef = new SoftReference(buffer);
// Eliminate the strong reference
buffer = null;
// ...
// Create a new strong reference
byte[] bufferData = (byte[])(bufferRef.get());
Note, however, that the get() method will return a null value if the reference was reclaimed by the garbage collector after the weak reference was created. Therefore, when you do use get() to attempt to access the referent, you should ensure that it did not return a null before you use the return value.An object is classified based on the strongest type of reference that exists to that object, and will be one of the following five values:
A strongly reachable object has strong references and may have soft, weak, or phantom references.
A softly reachable object has soft references and may have weak or phantom references, but does not have strong references.
A weakly reachable object has weak references and may have phantom references, but does not have strong or soft references.
A phantomly reachable object has only phantom references; it does not have strong, soft, or weak references.
An unreachable object is one for which there are no references of any kind.
In contrast, an object that is referenced through a chain of references is only as reachable as the weakest reference in the chain. For example, the following illustrates how a string of references can be created: SoftReference sr = new SoftReference(new WeakReference(new Date()));
In this case, the Date instance is only weakly reachable, because it is referenced through a chain of two references, one of which is a WeakReference.At this point, you may be wondering why there are three different types of weak references, and how their behavior differs. SoftReference and WeakReference are very similar in function and behavior, but there is one important difference. Garbage collector implementations are discouraged (but not prevented) from reclaiming softly reachable objects, especially those that have been created or accessed recently. In contrast, the garbage collector will reclaim a weakly reachable object just as if no references existed to it at all.Phantom references are very different from the other two types, and are intended to be used specifically to allow you to determine when an object is about to be destroyed by the garbage collector. In fact, the get() method of a PhantomReference always returns null, even when the referent has not yet been garbage collected. After the referent's finalize() method has been called but before it is destroyed, any PhantomReference instances that refer to the referent are added to the appropriate ReferenceQueue. Garbage collection of the referent will not be completed until the PhantomReference's clear() method is called, so it is the responsibility of your application to do so when using phantom references. Your code should wait for PhantomReference instances to be placed on the queue by the garbage collector, perform the appropriate cleanup for the referent, and then call the clear() method to allow the referent to be reclaimed.The methods defined in ReferenceQueue simply allow you to retrieve Reference objects that have been placed on the queue. One implementation of the remove() method waits indefinitely until a Reference appears in the queue and returns that object. The other version of remove() allows you to specify the maximum number of milliseconds that it will wait for a Reference to be queued, and if none becomes available within that time, it returns a null value. Finally, the poll() method always returns immediately, providing the caller with either a Reference that was queued or with a null value if none is available. In other words, the remove() method blocks the calling thread until an entry is available in queue or until the specified amount of time elapses, while poll() never blocks the caller.How Reference Objects can be UsedNow that the behavior of the three Reference subclasses has been described, we'll briefly examine how each one can be used. Although many of the examples shown here use the java.lang.ref classes directly, you'll often find it more useful to subclass one of those when using weak references with your application. By creating a subclass, you can associate more information with the reference about how it is used and/or what action to take when you detect that its referent was cleared.SoftReferenceYou can use SoftReference instances to cache information that should be discarded when your application begins to run low on memory. For example, if you're reading information from a database or files from a web browser, it may be useful to cache that data in memory as long as it does not cause your application to run out of memory. When the application needs to read information that was previously retrieved from the database or the network, it can first check the SoftReference-based cache. If the reference has not been cleared, the data can be quickly returned from the memory cache, but if it has been cleared, the data can again be retrieved from the database or network.WeakReferenceYou'll sometimes wish to associate information with an object without preventing that object from being garbage collected, and you'll want the information to be destroyed when the object is reclaimed. If you were to use a "traditional" (strong) reference to associate the object with its information the object would never be garbage collected. For example, suppose that you use a Hashtable to maintain a relationship between objects and their information as shown below: Hashtable ht = new Hashtable();
// ...
MyObject myObj = new MyObject();
ht.put(myObj, "This is the associated information");
The problem with this approach is that as long as a reference to the Hashtable exists and as long as it contains a strong reference to the MyObject instance, that object will never be reclaimed. However, by creating an association with a WeakReference, you can define a mapping that lasts only for the lifetime of the MyObject instance without affecting the garbage collector's ability to reclaim the object. In fact, that is exactly what the java.util.WeakHashMap class does, and an example of how it might be used is provided below: WeakHashMap map = new WeakHashMap();
// ...
MyObject myObj = new MyObject();
map.put(myObj, "This is the associated information");
Each key in a WeakHashMap is an instance of a subclass of WeakReference, which allows the MyObject instance to be reclaimed by the garbage collector when there are no more strong references to it. Once that does occur, the WeakReference key entry in the map will remain, but its referent will be cleared and it will be placed on a ReferenceQueue. When an entry is added to or removed from the WeakHashMap, it checks the queue to see if any of its entries have been cleared and removes those that represent items that were garbage collected.PhantomReferenceAs mentioned earlier, the purpose of the PhantomReference is to allow you to perform cleanup tasks for objects before they are destroyed by the garbage collector. Use of a ReferenceQueue with a SoftReference or WeakReference is optional, but each PhantomReference you construct must be associated with a ReferenceQueue as shown below: MyObject myObj = new MyObject();
ReferenceQueue rq = new ReferenceQueue();
PhantomReference pr = new PhantomReference(myObj, rq);
You may wish to create a separate thread that waits for entries to be added to a ReferenceQueue, or you might design your code so that it periodically calls the poll() method. When a PhantomReference is retrieved from the queue, the appropriate cleanup should be performed for its reference and the clear() method called to allow the referent to be garbage collected.SummaryIn this chapter, we have looked at:
Using HPROF to examine the performance of a Java application, and to locate the source of a performance problem
Tips for improving the performance of your applications
The various types of Java compilers that are available, including Just-In-Time compilers and Sun's HotSpot technology
Memory management, including examination of garbage collection and reference objects