Friday, July 21, 2006
Wednesday, July 19, 2006
Secrets Of The Masters: Core Java Interview Questions
For most questions I’ve provided only short answers to encourage further research. I have included only questions for mid (*) and senior level (**) Java developers. These sample questions could also become handy for people who need to interview Java developers (see also the article "Interviewing Enterprise Java Developers").
30 Java Interview Questions
* Q1. How could Java classes direct program messages to the system console, but error messages, say to a file?
A. The class System has a variable out that represents the standard output, and the variable err that represents the standard error device. By default, they both point at the system console. This how the standard output could be re-directed:
Stream st = new Stream(new FileOutputStream("output.txt")); System.setErr(st); System.setOut(st);
* Q2. What's the difference between an interface and an abstract class?
A. An abstract class may contain code in method bodies, which is not allowed in an interface. With abstract classes, you have to inherit your class from it and Java does not allow multiple inheritance. On the other hand, you can implement multiple interfaces in your class.
* Q3. Why would you use a synchronized block vs. synchronized method?
A. Synchronized blocks place locks for shorter periods than synchronized methods.
* Q4. Explain the usage of the keyword transient?
A. This keyword indicates that the value of this member variable does not have to be serialized with the object. When the class will be de-serialized, this variable will be initialized with a default value of its data type (i.e. zero for integers).
* Q5. How can you force garbage collection?
A. You can't force GC, but could request it by calling System.gc(). JVM does not guarantee that GC will be started immediately.
* Q6. How do you know if an explicit object casting is needed?
A. If you assign a superclass object to a variable of a subclass's data type, you need to do explicit casting. For example:
Object a; Customer b; b = (Customer) a;
When you assign a subclass to a variable having a supeclass type, the casting is performed automatically.
* Q7. What's the difference between the methods sleep() and wait()
A. The code sleep(1000); puts thread aside for exactly one second. The code wait(1000), causes a wait of up to one second. A thread could stop waiting earlier if it receives the notify() or notifyAll() call. The method wait() is defined in the class Object and the method sleep() is defined in the class Thread.
* Q8. Can you write a Java class that could be used both as an applet as well as an application?
A. Yes. Add a main() method to the applet.
* Q9. What's the difference between constructors and other methods?
A. Constructors must have the same name as the class and can not return a value. They are only called once while regular methods could be called many times.
* Q10. Can you call one constructor from another if a class has multiple constructors
A. Yes. Use this() syntax.
* Q11. Explain the usage of Java packages.
A. This is a way to organize files when a project consists of multiple modules. It also helps resolve naming conflicts when different packages have classes with the same names. Packages access level also allows you to protect data from being used by the non-authorized classes.
* Q12. If a class is located in a package, what do you need to change in the OS environment to be able to use it?
A. You need to add a directory or a jar file that contains the package directories to the CLASSPATH environment variable. Let's say a class Employee belongs to a package com.xyz.hr; and is located in the file c:\dev\com\xyz\hr\Employee.java. In this case, you'd need to add c:\dev to the variable CLASSPATH. If this class contains the method main(), you could test it from a command prompt window as follows:
c:\>java com.xyz.hr.Employee
* Q13. What's the difference between J2SDK 1.5 and J2SDK 5.0?
A.There's no difference, Sun Microsystems just re-branded this version.
* Q14. What would you use to compare two String variables - the operator == or the method equals()?
A. I'd use the method equals() to compare the values of the Strings and the == to check if two variables point at the same instance of a String object.
* Q15. Does it matter in what order catch statements for FileNotFoundException and IOExceptipon are written?
A. Yes, it does. The FileNoFoundException is inherited from the IOException. Exception's subclasses have to be caught first.
* Q16. Can an inner class declared inside of a method access local variables of this method?
A. It's possible if these variables are final.
* Q17. What can go wrong if you replace && with & in the following code:
String a=null; if (a!=null && a.length()>10) {...}
A. A single ampersand here would lead to a NullPointerException.
* Q18. What's the main difference between a Vector and an ArrayList
A. Java Vector class is internally synchronized and ArrayList is not.
* Q19. When should the method invokeLater()be used?
A. This method is used to ensure that Swing components are updated through the event-dispatching thread.
* Q20. How can a subclass call a method or a constructor defined in a superclass?
A. Use the following syntax: super.myMethod(); To call a constructor of the superclass, just write super(); in the first line of the subclass's constructor.
Questions for senior developer job positions follow on the next page...
For senior-level developers:
** Q21. What's the difference between a queue and a stack?
A. Stacks works by last-in-first-out rule (LIFO), while queues use the FIFO rule
** Q22. You can create an abstract class that contains only abstract methods. On the other hand, you can create an interface that declares the same methods. So can you use abstract classes instead of interfaces?
A. Sometimes. But your class may be a descendent of another class and in this case the interface is your only option.
** Q23. What comes to mind when you hear about a young generation in Java?
A. Garbage collection.
** Q24. What comes to mind when someone mentions a shallow copy in Java?
A. Object cloning.
** Q25. If you're overriding the method equals() of an object, which other method you might also consider?
A. hashCode()
** Q26. You are planning to do an indexed search in a list of objects. Which of the two Java collections should you use:
ArrayList or LinkedList?
A. ArrayList
** Q27. How would you make a copy of an entire Java object with its state?
A. Have this class implement Cloneable interface and call its method clone().
** Q28. How can you minimize the need of garbage collection and make the memory use more effective?
A. Use object pooling and weak object references.
** Q29. There are two classes: A and B. The class B need to inform a class A when some important event has happened. What Java technique would you use to implement it?
A. If these classes are threads I'd consider notify() or notifyAll(). For regular classes you can use the Observer interface.
** Q30. What access level do you need to specify in the class declaration to ensure that only classes from the same directory can access it?
A. You do not need to specify any access level, and Java will use a default package access level.
(http://it.sys-con.com/read/48839_p.htm)
What is Defensive Copying
So what is defensive copying, also sometime known as object copy.
Defensive copying is concerned with protecting mutable objects e.g. objects who's state can be modified by the user. If you were pass back the reference of an object any changes a user made to that copy of the object would effect your object because you are only passes a reference to the object and not the actual object itself. This is known as a shallow copy.
To avoid users being able to change the values of your object you can pass back a defensive copy. This means that instead of passing back a reference to your object it passes back a new object but with the same values. This means that any changes the user makes to that copy of the object doesn't change the value/state of your object.
It's an interesting idea but I can't think of a use for this at the moment but I'm sure one day this will come in useful.
Here are a couple of links to some probably better explanations with an example
http://www.javapractices.com/Topic15.cjp
http://en.wikipedia.org/wiki/Defensive_copy
The first site Java practices has lots of useful articles and well worth checking out
(http://hoskinator.blogspot.com/2006/07/what-is-defensive-copying.html)
Thursday, June 22, 2006
10 tips on writing reusable code
So recently I have been trying to write code which I can reuse. It has been interesting that since I have been doing this I have noticed that my library of code is starting to grow. I have started to create more Static Helper classes with useful methods in. I have also been removing the business logic away from any Struts actions or framework work.
To do this I have tried to do a number of things to help this and these are the sort of rules and things I do (in no order) to help me try and achieve this. They are a number of rules and tips I have picked up but can't remember where from
1. Keep the code DRY. Dry means Don't repeat yourself. This is one of the main changes I have tried to bring in. Always try to eradicate duplication and if you find any then move remove the duplication to a relevant place. Sometimes this has lead me to create Static Helper classes or sometimes move it to the class it makes most sense to have it.
2. Make a class/method do just one thing. This is along the lines of the advice of giving the class only one reason to change. This often means creating methods that other methods use but this helps to make the methods/classes simple and less coupled.
3. Write unit tests for your classes AND make it easy to test classes. Writing code that is easy to test is decoupled. If you write code and are thinking about writing a unit test for it then you tend to split up the code into smaller testable chunks.
4. Remove the business logic or main code away from any framework code. Following the rules above will help this. An example I have seen is code that is inside Struts Actions classes, this code is practically impossible to reuse because of all the Struts dependencies that it now linked with.
5. Try to think more abstractly and use Interfaces and Abstract classes. Try to hide dependencies of code behind a more Generic interface/abstract class. The benefit this gives the code is it creates a flexible point in the code where you can then hide future changes behind.
6. Code for extension. Write code that can easily be extended in the future. This is particularly true with the above point. If you write code that uses interfaces then you can extend that interface at a later point.
7. Don't write code that isn't needed. Do the simplest thing possible. Don't waste your time adding methods and classes that might be used in the future. Keep the code simple and focused on what you are trying to deliver. I think I read/heard Josh Bloch say once that "if in doubt, leave it out". Basically who wants to write code that no one (including yourself) is going to use again.
8. Try to reduce coupling. When writing code think about the links and coupling the code is creating, does it need to be linked to those other classes.
9. Be more Modular - make your code more modular, think modular, be modular.
10. Write code like your code is an External API. Imagine the code you are writing is a self contained component.
It wasn't going to be ten until I got to 8 and then thought no one writes 8 tips, lets add two more on. It isn't really a list but it's sort of aims and mental notes I try tell myself when writing code. They are more small bits of code I have written recently that has helped. I would like to hear people's comments and especially their tips on writing reusable code.
(http://cg.scs.carleton.ca/~morin/misc/sortalg/)
Unix: Ten Things Every Java Developer Should Know
Developing code meant for Unix on Windows does work reasonably well. The trouble is, many those coders slaving away in front of XP have a very limited understanding of their target platform. If that describes you, this following list is meant for you. Without further ado, here are the ten things you really need to know about Unix, in reverse David Letterman order:
10) You need to be special to use some ports
On Unix machines, programs run by ordinary mortals cannot use network ports less than 1024. Only the special root user can use these ports. If you do decide that you need to run your server as root, be very careful since a program running as root is all powerful on a Unix machine.
9) There is no magic file locking
Windows has this magic file locking mechanism that prevents people from removing a file while it is open. Thus, on a Windows box the call to delete() in the following code is pretty much sure to fail:
InputStream is = new FileInputStream("foo.txt");
(new File("foo.txt")).delete();
int ch;
while( (ch = is.read()) > 0 )
System.out.println( "char: " + (char)ch );
is.close();
The delete will fail because someone (our program in fact) has the file open. After we get done printing out its contents, foo.txt will still be there. The kicker is, the delete() will work just fine on any Unix box. Under Unix, the call to delete() will delete the entry for foo.txt out from the file system, but since someone (our program) still has the file open, the bytes will live on, to be read and printed out. Only when we close the stream will the contents of foo.txt follow its name into oblivion.
In exactly the same way, on a Unix box, someone can delete a program's current directory right out from underneath it.
8) Sometimes there is no GUI
People who are used to Windows are sometimes surprised to find their programs running on a Unix box that has no GUI at all. None. Zilch. Nada. In Unix, the GUI is an add on component and it is completely optional. The machine will run fine without it and servers commonly do. Be very careful making calls to those handy java.awt methods -- some of them will fail on a machine with no GUI.
While you are at it, you may want to rethink what you are writing out with System.out. Many severs not only lack a GUI, they are completely headless: no keyboard, no mouse, no screen. If you are deploying into this kind of environment, the log file is your friend, because your program's cries for help are unlikely to be heard anywhere else.
7) In Unix, there is no registry...
... but if there was, it would be a plain text file. Unix systems have no central place like the Windows registry for storing configuration information. Instead, Unix configuration is spread over a fair number of different files. Many of these files live in a directory called /etc : the list of users is in a file called /etc/passwd, while the name of the machine is typically found in /etc/host.
I guess if you are a Windows user that is the bad news. Here is the good news: most, if not all of the configuration files are plain text files. You can look at them with any old text editor. A further bit of good news is that all modern Unix like systems come with GUIs to edit the configuration files.
6) Forward slashes are your friend
This one is really more about Java on Windows than it is about Unix, but useful anyway. Just about everyone knows that Unix uses forward slashes to separate the bits of a path: /etc/passwd, while Windows uses backslashes: c:\Program Files\Windows. What a disturbing number of folks don't realize is that forward slashes work just fine on in Java on Windows too. On a Windows box, Java is smart enough to translate /a/b/c/foo.txt to something like C:\a\b\c\foo.txt.
Should you rely on this for production? No. If you are really coding cross platform Java, you need know about File.pathSeparator and the various File constructors. But if you are coding stuff that is only meant for Unix, and you just want to test it on your windows box, knowing that the forward slashes work in both places can save a lot of agony.
5) Our services are just programs
In Windows, system services are special programs, written to a particular service API. On Unix, services are provided by pretty ordinary programs that do service like things.
Typically, a Unix service consists of the useful program and a script which starts the program in the background when the system starts up and may shut it down again when the system is halting. Many Unix systems keep these scripts in the /etc/init.d directory.
4) Environment variables are hard to change
Windows programmers sometimes cook up little batch files that set the environment variables they want. Perhaps you need to roll back to an old version of Java and Ant. You might write a batch file that looks something like:
set JAVA_HOME=C:\java1.4.1_05
set ANT_HOME=C:\apache-ant-1.6.1
They can then run the batch file:
c:\> setenv.bat
and have the environment that you need. If you try to translate this directly into Unix-land, you get a script that looks not too different:
#!/bin/sh
JAVA_HOME=/usr/java1.4.1_05
export JAVA_HOME
ANT_HOME=/usr/apache-ant-1.6.1
export ANT_HOME
So you try out your new script...
$ setenv.sh
...and it does nothing. The trouble is that the Unix shell runs scripts by creating a copy of itself and running the script in the new shell. This new shell will read in the script, set all the environment variables and then exit, leaving the original shell and its environment unchanged. I hate when that happens. Changing directories works pretty much the same way: if you do a cd in an ordinary shell script, it will change the directory for that second shell, which may or may not be what you want.
If what you want is to change things in your current shell, you need to have the current shell read in the script directly, without starting a new shell to do the job. You can do this with by using the dot command:
. setenv.sh
Life will be good as your environment variables change.
I should mention that there are several different shells available in Unix. Which one you use is mostly a matter of taste, either yours or the person who set up your account. The commands above will work with many of the common Unix shells, but if you happen to be running the C shell (note the pun), then your little script will need to look something like:
setenv JAVA_HOME /usr/java1.4.1_05
setenv ANT_HOME /usr/apache-ant-1.6.1
You also need a different command to read the script in:
source setenv.csh
3) We don't like spaces in our file names
Okay, this one probably has more to do with Unix users and sys admins than the OS itself, but the fact is, we don't like spaces in our paths. Oh it is perfectly possibly to have spaces in Unix file names. In fact you can put darn near anything in a Unix file name: /tmp/:a,*b%c is actually the name of a directory on the system that I am using to write this.
But can and should are two different things. Unix users spend much of their time using the command line and Unix command line utilities are not crazy about paths with stars, question marks and especially spaces. The Unix guy can always find a way, but if you insist on putting strange characters like spaces in your file names, you are just finding a way to annoy your local Unix guy.
2) There is no carriage to return
If I had just one magic lighting bolt to hurl at one person, I think I would pick the guy who decided to use different line terminating characters on the two major OS's. I suspect we would have hyper intelligent computers by now were it not for all the time wasted trying to figure out why my file looks funny on your OS.
In a plain text file, Windows typically uses a carriage return followed by a newline character to mark the end of a line. Unix dispenses with the carriage return and makes due with the single newline character. Although the tools are getting better, Unix style files may show up as one long line in Windows -- not a single carriage return/newline pair in that file, must be a single line. Likewise, Windows style files will sometimes show up on Unix with garbage characters at the end of a line -- that extra carriage return is meaningless under the Unix convention.
This doesn't matter much for Java files -- it's all white space to the Java compiler. But some native Unix programs care passionately about those funny characters at the end of a line. In particular if you use a Windows based tool to edit a Unix script and your tool adds carriage returns to the script file, you have screwed it up. The script will no longer run. Worse, since many Unix editors do now handle the carriage returns, you could look at the broken script and see nothing wrong.
1) You need a Linux box
If you are doing significant development for Unix, you owe it to yourself and your customers to know something about Unix. If all else fails, get yourself an old PC and some of that free Linux. Or get yourself one of the many bootable Linux-on-a-CD distributions and try it out on any machine. Java is nearly platform independent, but not quite. It is up to you to make up the difference.
(http://www.javalobby.org/articles/10things-unix/)
Tuesday, June 13, 2006
New Robot Has Powerful Cling by Tracy Staedter
The City Climber rover, being developed by Jizhong Xiao and his team at the City College of New York, uses a vacuum chamber to get vertical. The robot is part of a project that aims to automate mandatory building inspections.
"New York City mandates that the facades of buildings be inspected every five years," said Xiao. "But the current manual inspection is time-consuming and the cost is very high — about $5,000 for one day."
Xiao thinks his robot, which costs less than one day’s work, can do the job faster, cheaper, and more thoroughly than trained technicians, who typically perform their gravity-defying work from suspended scaffolding.
Robotic wall climbers typically employ more superhero-like methods: sticky feet, suction cups, claws, or magnets. But those grippers are only as good as the surface they make contact with.
Suction cups or sticky feet, for example, work best on smooth surfaces such as glass or marble, but not so well on brick. Clawed toes clamber well over rock and brick but slip on glass.
What’s more, such devices tend to move tentatively and cannot navigate over a variety of textured surfaces.
Getting a robot to both cling to a wall and maneuver effortlessly over it are among the two biggest challenges that face researchers focused on wall-climbing robots, said Ning Xi, director of the Laboratory of Robotics and Automation at Michigan State University.
"In both aspects, the City Climber is probably the best in the world right now," said Xi, who is not associated with the project.
The 1-kilogram device clings to the wall by way of a vacuum rotor located in the center of its underbelly. The rotor’s impeller draws air in from the center of the device and spews it out toward the edges.
The column of circulating air creates a region of low air pressure inside the vacuum chamber. Because the surrounding air pressure is higher, it pushes down on the device, keeping it tight to the wall.
Small wheels on the underbelly of the device drive the robot forward and back.
By linking two triangular-shaped modules with a hinged arm, the researchers were able to make the City Climber maneuver around 90-degree angle corners and transition from a wall to a roof — all with the strength to pull or carry a payload four times its weight.
"They have achieved one of the highest payloads reported in the literature," said
professor Nikos Papanikolopoulos of the University of Minnesota.
Xiao will be capitalizing on his rover’s payload capabilities this summer by equipping it with a high-resolution digital camera to conduct a mock building inspection.
(http://dsc.discovery.com/news/briefs/20060612/cityclimber_tec_print.html)
Friday, June 09, 2006
Computer 'Beings' Evolve as Society by Tracy Staedter
Millions of computer-generated entities that live and die by natural selection could reveal how our own culture and language evolve.
The software agents are part of a project called NEW TIES (New and Emergent World Models Through Individual, Evolutionary, and Social Learning), which draws on the expertise of five European research institutions to push computer simulation of artificial worlds further than ever before.
The joint computer project not only reproduces individual and evolutionary learning, but also social learning.
"Social learning is these guys telling each other what they learn on their own. One is learning about hot and cold and another is learning about soft and hard.
"They exchange knowledge and save effort," explained project coordinator Gusz Eiben, a professor of artificial intelligence at the Vrije University, Amsterdam.
Understanding gleaned from such a project could advance machine learning for a range of applications. The learning software could guide exploratory or search and rescue robots that must cooperate to accomplish tasks in unknown environments.
The simulation computer project could even allow policy makers to test out new laws before carrying them out in real life.
The team of computer scientists, sociologists and linguists are creating a population of millions of unique entities that have the ability to pass on life-prolonging tips to their community. In the process, they may evolve their own language.
Computers Create Unique Beings
Each agent is randomly generated by a computer to possess a gender and different variations of life expectancy, fertility, size, and metabolism. The randomness of their programs allows each one to behave differently even when faced with the same set of circumstances.
The outcome of their actions — moving around, talking with another entity, and giving birth — burns fuel that can be replenished by finding the right food source.
Those who lack the wherewithal to survive risk certain death and the inability to propagate their genes.
A simple vocabulary of five to tens words, such as "food," "near" and "agent" gives the entities the basics for communication.
Meanwhile, an algorithm enables two entities to agree on the meaning of new words and could allow the artificial beings to evolve a language.
The idea is to expose the agents to challenges and see how they adapt and develop their own world models.
Recently, Eiben and his team began running their first simulations using 1,000 to 3,000 agents to ask the question: Does individual learning compensate for bad genes? Eventually they plan to scale up to millions of agents.
The big challenge the team faces, said senior researcher Michele Sebag, an expert in artificial intelligence at the University of Paris-Sud, is tracking the behavior of each of the millions of agents.
"You can't look at every agent individually. You have to have new facilities in data mining to understand what is going on in your population," she said.
Following the rationale that "birds of feather stick together," Gusz will be pinpointing and profiling agents who cluster together as well as tracking the locations of each agent as it moves over time.
Thursday, June 08, 2006
java.lang.ThreadLocal
The application I modified is a basic batch maintenance JDBC type of stand-alone application that reads a text file and updates a database. In order to speed things up, the application was parallelized (if that is a word).
The problem was that the DB2 java.sql.Connection object (which was being retrieved from a custom factory) was not thread-safe. So I opted to use an individual Connection per thread. But how to implement this strategy?
I could have used a connection pool (FOSS or rolled) to help out, but there were a bunch of reasons why I didn't, here's a sampling:
- The app is small and lean. Adding 3rd party pooling would be considered bloat, writing one myself would be a waste of time.
- No sharing benefit; one app runs per JVM. If the system were deployed on an app server, where multiple apps could benefit from the same pool, the centralized management might be worth it.
I chose to wrap the Connection in ThreadLocal instead. Then redirect all calls for a connection (in the factory) to ThreadLocal.get().
The class snippet below doesn't really work but it illustrates the point.
public static Connection getConnection() {
return (Connection) conn.get();
}
private static ThreadLocal conn = new ThreadLocal() {
public Object initialValue() {
String driverClass = "whatever";
try {
Class.forName(driverClass);
Connection con =
DriverManager.getConnection("connectionURL",
"user", "password");
con.setReadOnly(true);
con.setAutoCommit(false);
return con;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
};
It worked like a champ.. every thread that called getConnection() got a different Connection and the threads could do their work independently.(http://mattfleming.com/node/118)
Analysing GC the affordable way
Lately i have been running into memory problems at a customer and i was ready to go with a to be bought profiler to the customer and play the profiler game. But after visiting or contacting most of the major players in the profiler segment like JProfiler, JProbe, Yourkit or OptimizeIT, i had to realize that the complete crowd dont support Java on Linux/PPC. First i thought that this cant be real because nearly all IBM machines and therefore nearly all IBM customers are running linux on Power Architecture (except xSeries of course). But it is real and so far i dont know any profiler which is running there.
So i searched for alternatives and used the JVM boardtools like verboseGC and the new Java5 switches for memory profiling. After getting some more log files from the JVM, i found the "IBM Pattern Modeling and Analysis Tool for Java Garbage Collector" quite useful. BTW you can get it here. So i run this tool with my first verboseGC log and even its not an exhausting information, its enough to get the idea and to look further. Below the screenshot. There are some more tools in this space from IBM i will cover in the next days.
(http://www.logemann.org/blojsom/blog/default/?permalink=analysing-GC-the-affordable-way.html)
Wednesday, May 24, 2006
Web inventor warns of 'dark' net by Jonathan Fildes
The web should remain neutral and resist attempts to fragment it into different services, web inventor Sir Tim Berners-Lee has said.
Recent attempts in the US to try to charge for different levels of online access web were not "part of the internet model," he said in Edinburgh.
He warned that if the US decided to go ahead with a two-tier internet, the network would enter "a dark period".
Sir Tim was speaking at the start of a conference on the future of the web.
"What's very important from my point of view is that there is one web," he said.
"Anyone that tries to chop it into two will find that their piece looks very boring."
An equal net
The British scientist developed the web in 1989 as an academic tool to allow scientists to share data. Since then it has exploded into every area of life.
"You get this tremendous serendipity where I can search the internet and come across a site that I did not set out to look for"
Tim Berners-Lee
However, as it has grown, there have been increasingly diverse opinions on how it should evolve.
The World Wide Web Consortium, of which Sir Tim is the director, believes in an open model.
This is based on the concept of network neutrality, where everyone has the same level of access to the web and that all data moving around the web is treated equally.
This view is backed by companies like Microsoft and Google, who have called for legislation to be introduced to guarantee net neutrality.
The first steps towards this were taken last week when members of the US House of Representatives introduced a net neutrality bill.
Pay model
But telecoms companies in the US do not agree. They would like to implement a two-tier system, where data from companies or institutions that can pay are given priority over those that cannot.
This has particularly become an issue with the transmission of TV shows over the internet, with some broadband providers wanting to charge content providers to carry the data.
The internet community believes this threatens the open model of the internet as broadband providers will become gatekeepers to the web's content.
Providers that can pay will be able to get a commercial advantage over those that cannot.
There is a fear that institutions like universities and charities would also suffer.
The web community is also worried that any charges would be passed on to the consumer.
Optimism
Sir Tim said this as "not the internet model". The "right" model, as exists at the moment, was that any content provider could pay for a connection to the internet and could then put any content on to the web with no discrimination.
Speaking to reporters in Edinburgh at the WWW2006 conference, he argued this was where the great benefit of the internet lay.
"You get this tremendous serendipity where I can search the internet and come across a site that I did not set out to look for," he said.
A two-tier system would mean that people would only have full access to those portions of the internet that they paid for and that some companies would be given priority over others.
But Sir Tim was optimistic that the internet would resist attempts to fragment.
"I think it is one and will remain as one," he said.
(http://news.bbc.co.uk/)
Dealing with InterruptedException by Brian Goetz
Many Java™ language methods, such as Thread.sleep() and Object.wait(), throw InterruptedException. You can't ignore it because it's a checked exception, but what should you do with it? In this month's Java theory and practice, concurrency expert Brian Goetz explains what InterruptedException means, why it is thrown, and what you should do when you catch one.
This story is probably familiar: You're writing a test program and you need to pause for some amount of time, so you call Thread.sleep(). But then the compiler or IDE balks that you haven't dealt with the checked InterruptedException. What is InterruptedException, and why do you have to deal with it?
The most common response to InterruptedException is to swallow it -- catch it and do nothing (or perhaps log it, which isn't any better) -- as we'll see later in Listing 4. Unfortunately, this approach throws away important information about the fact that an interrupt occurred, which could compromise the application's ability to cancel activities or shut down in a timely manner.
Blocking methods
When a method throws InterruptedException, it is telling you several things in addition to the fact that it can throw a particular checked exception. It is telling you that it is a blocking method and that it will make an attempt to unblock and return early -- if you ask nicely.
A blocking method is different from an ordinary method that just takes a long time to run. The completion of an ordinary method is dependent only on how much work you've asked it to do and whether adequate computing resources (CPU cycles and memory) are available. The completion of a blocking method, on the other hand, is also dependent on some external event, such as timer expiration, I/O completion, or the action of another thread (releasing a lock, setting a flag, or placing a task on a work queue). Ordinary methods complete as soon as their work can be done, but blocking methods are less predictable because they depend on external events. Blocking methods can compromise responsiveness because it can be hard to predict when they will complete.
Because blocking methods can potentially take forever if the event they are waiting for never occurs, it is often useful for blocking operations to be cancelable. (It is often useful for long-running non-blocking methods to be cancelable as well.) A cancelable operation is one that can be externally moved to completion in advance of when it would ordinarily complete on its own. The interruption mechanism provided by Thread and supported by Thread.sleep() and Object.wait() is a cancellation mechanism; it allows one thread to request that another thread stop what it is doing early. When a method throws InterruptedException, it is telling you that if the thread executing the method is interrupted, it will make an attempt to stop what it is doing and return early and indicate its early return by throwing InterruptedException. Well-behaved blocking library methods should be responsive to interruption and throw InterruptedException so they can be used within cancelable activities without compromising responsiveness.
Thread interruption
Every thread has a Boolean property associated with it that represents its interrupted status. The interrupted status is initially false; when a thread is interrupted by some other thread through a call to Thread.interrupt(), one of two things happens. If that thread is executing a low-level interruptible blocking method like Thread.sleep(), Thread.join(), or Object.wait(), it unblocks and throws InterruptedException. Otherwise, interrupt() merely sets the thread's interruption status. Code running in the interrupted thread can later poll the interrupted status to see if it has been requested to stop what it is doing; the interrupted status can be read with Thread.isInterrupted() and can be read and cleared in a single operation with the poorly named Thread.interrupted().
Interruption is a cooperative mechanism. When one thread interrupts another, the interrupted thread does not necessarily stop what it is doing immediately. Instead, interruption is a way of politely asking another thread to stop what it is doing if it wants to, at its convenience. Some methods, like Thread.sleep(), take this request seriously, but methods are not required to pay attention to interruption. Methods that do not block but that still may take a long time to execute can respect requests for interruption by polling the interrupted status and return early if interrupted. You are free to ignore an interruption request, but doing so may compromise responsiveness.
One of the benefits of the cooperative nature of interruption is that it provides more flexibility for safely constructing cancelable activities. We rarely want an activity to stop immediately; program data structures could be left in an inconsistent state if the activity were canceled mid-update. Interruption allows a cancelable activity to clean up any work in progress, restore invariants, notify other activities of the cancellation, and then terminate.
Dealing with InterruptedException
If throwing InterruptedException means that a method is a blocking method, then calling a blocking method means that your method is a blocking method too, and you should have a strategy for dealing with InterruptedException. Often the easiest strategy is to throw InterruptedException yourself, as shown in the putTask() and getTask() methods in Listing 1. Doing so makes your method responsive to interruption as well and often requires nothing more than adding InterruptedException to your throws clause.
Listing 1. Propagating InterruptedException to callers by not catching it
public class TaskQueue {
private static final int MAX_TASKS = 1000;
private BlockingQueue queue
= new LinkedBlockingQueue(MAX_TASKS);
public void putTask(Task r) throws InterruptedException {
queue.put(r);
}
public Task getTask() throws InterruptedException {
return queue.take();
}
}
Sometimes it is necessary to do some amount of cleanup before propagating the exception. In this case, you can catch InterruptedException, perform the cleanup, and then rethrow the exception. Listing 2, a mechanism for matching players in an online game service, illustrates this technique. The matchPlayers() method waits for two players to arrive and then starts a new game. If it is interrupted after one player has arrived but before the second player arrives, it puts that player back on the queue before rethrowing the InterruptedException, so that the player's request to play is not lost.
Listing 2. Performing task-specific cleanup before rethrowing InterruptedException
public class PlayerMatcher {
private PlayerSource players;
public PlayerMatcher(PlayerSource players) {
this.players = players;
}
public void matchPlayers() throws InterruptedException {
try {
Player playerOne, playerTwo;
while (true) {
playerOne = playerTwo = null;
// Wait for two players to arrive and start a new game
playerOne = players.waitForPlayer(); // could throw IE
playerTwo = players.waitForPlayer(); // could throw IE
startNewGame(playerOne, playerTwo);
}
}
catch (InterruptedException e) {
// If we got one player and were interrupted, put that player back
if (playerOne != null)
players.addFirst(playerOne);
// Then propagate the exception
throw e;
}
}
}
Don't swallow interrupts
Sometimes throwing InterruptedException is not an option, such as when a task defined by Runnable calls an interruptible method. In this case, you can't rethrow InterruptedException, but you also do not want to do nothing. When a blocking method detects interruption and throws InterruptedException, it clears the interrupted status. If you catch InterruptedException but cannot rethrow it, you should preserve evidence that the interruption occurred so that code higher up on the call stack can learn of the interruption and respond to it if it wants to. This task is accomplished by calling interrupt() to "reinterrupt" the current thread, as shown in Listing 3. At the very least, whenever you catch InterruptedException and don't rethrow it, reinterrupt the current thread before returning.
Listing 3. Restoring the interrupted status after catching InterruptedException
public class TaskRunner implements Runnable {
private BlockingQueue queue;
public TaskRunner(BlockingQueue queue) {
this.queue = queue;
}
public void run() {
try {
while (true) {
Task task = queue.take(10, TimeUnit.SECONDS);
task.execute();
}
}
catch (InterruptedException e) {
// Restore the interrupted status
Thread.currentThread().interrupt();
}
}
}
The worst thing you can do with InterruptedException is swallow it -- catch it and neither rethrow it nor reassert the thread's interrupted status. The standard approach to dealing with an exception you didn't plan for -- catch it and log it -- also counts as swallowing the interruption because code higher up on the call stack won't be able to find out about it. (Logging InterruptedException is also just silly because by the time a human reads the log, it is too late to do anything about it.) Listing 4 shows the all-too-common pattern of swallowing an interrupt:
Listing 4. Swallowing an interrupt -- don't do this
// Don't do this
public class TaskRunner implements Runnable {
private BlockingQueue queue;
public TaskRunner(BlockingQueue queue) {
this.queue = queue;
}
public void run() {
try {
while (true) {
Task task = queue.take(10, TimeUnit.SECONDS);
task.execute();
}
}
catch (InterruptedException swallowed) {
/* DON'T DO THIS - RESTORE THE INTERRUPTED STATUS INSTEAD */
}
}
}
If you cannot rethrow InterruptedException, whether or not you plan to act on the interrupt request, you still want to reinterrupt the current thread because a single interruption request may have multiple "recipients." The standard thread pool (ThreadPoolExecutor) worker thread implementation is responsive to interruption, so interrupting a task running in a thread pool may have the effect of both canceling the task and notifying the execution thread that the thread pool is shutting down. If the task were to swallow the interrupt request, the worker thread might not learn that an interrupt was requested, which could delay the application or service shutdown.
Back to top
Implementing cancelable tasks
Nothing in the language specification gives interruption any specific semantics, but in larger programs, it is difficult to maintain any semantics for interruption other than cancellation. Depending on the activity, a user could request cancellation through a GUI or through a network mechanism such as JMX or Web Services. It could also be requested by program logic. For example, a Web crawler might automatically shut itself down if it detects that the disk is full, or a parallel algorithm might start multiple threads to search different regions of the solution space and cancel them once one of them finds a solution.
Just because a task is cancelable does not mean it needs to respond to an interrupt request immediately. For tasks that execute code in a loop, it is common to check for interruption only once per loop iteration. Depending on how long the loop takes to execute, it could take some time before the task code notices the thread has been interrupted (either by polling the interrupted status with Thread.isInterrupted() or by calling a blocking method). If the task needs to be more responsive, it can poll the interrupted status more frequently. Blocking methods usually poll the interrupted status immediately on entry, throwing InterruptedException if it is set to improve responsiveness.
The one time it is acceptable to swallow an interrupt is when you know the thread is about to exit. This scenario only occurs when the class calling the interruptible method is part of a Thread, not a Runnable or general-purpose library code, as illustrated in Listing 5. It creates a thread that enumerates prime numbers until it is interrupted and allows the thread to exit upon interruption. The prime-seeking loop checks for interruption in two places: once by polling the isInterrupted() method in the header of the while loop and once when it calls the blocking BlockingQueue.put() method.
Listing 5. Interrupts can be swallowed if you know the thread is about to exit
public class PrimeProducer extends Thread {
private final BlockingQueue queue;
PrimeProducer(BlockingQueue queue) {
this.queue = queue;
}
public void run() {
try {
BigInteger p = BigInteger.ONE;
while (!Thread.currentThread().isInterrupted())
queue.put(p = p.nextProbablePrime());
} catch (InterruptedException consumed) {
/* Allow thread to exit */
}
}
public void cancel() { interrupt(); }
}
Noninterruptible blocking
Not all blocking methods throw InterruptedException. The input and output stream classes may block waiting for an I/O to complete, but they do not throw InterruptedException, and they do not return early if they are interrupted. However, in the case of socket I/O, if a thread closes the socket, blocking I/O operations on that socket in other threads will complete early with a SocketException. The nonblocking I/O classes in java.nio also do not support interruptible I/O, but blocking operations can similarly be canceled by closing the channel or requesting a wakeup on the Selector. Similarly, attempting to acquire an intrinsic lock (enter a synchronized block) cannot be interrupted, but ReentrantLock supports an interruptible acquisition mode.
Noncancelable tasks
Some tasks simply refuse to be interrupted, making them noncancelable. However, even noncancelable tasks should attempt to preserve the interrupted status in case code higher up on the call stack wants to act on the interruption after the noncancelable task completes. Listing 6 shows a method that waits on a blocking queue until an item is available, regardless of whether it is interrupted. To be a good citizen, it restores the interrupted status in a finally block after it is finished, so as not to deprive callers of the interruption request. (It can't restore the interrupted status earlier, as it would cause an infinite loop -- BlockingQueue.take() could poll the interrupted status immediately on entry and throws InterruptedException if it finds the interrupted status set.)
Listing 6. Noncancelable task that restores interrupted status before returning
public Task getNextTask(BlockingQueue queue) {
boolean interrupted = false;
try {
while (true) {
try {
return queue.take();
} catch (InterruptedException e) {
interrupted = true;
// fall through and retry
}
}
} finally {
if (interrupted)
Thread.currentThread().interrupt();
}
}
Back to top
Summary
You can use the cooperative interruption mechanism provided by the Java platform to construct flexible cancellation policies. Activities can decide if they are cancelable or not, how responsive they want to be to interruption, and they can defer interruption to perform task-specific cleanup if returning immediately would compromise application integrity. Even if you want to completely ignore interruption in your code, make sure to restore the interrupted status if you catch InterruptedException and do not rethrow it so that the code that calls it is not deprived of the knowledge that an interrupt occurred.
(http://www-128.ibm.com/developerworks/java/library/j-jtp05236.html?ca=drs)
Wednesday, May 17, 2006
Declarative Programming in Java by Narayanan Jayaratchagan
Narayanan Jayaratchagan is a Sun Certified J2EE Architect with more than six years of experience with Java and Microsoft Technologies.
What makes EJB components special is the declarative programming model through which we can specify the services such as security, persistence, transaction etc., that the container should provide. An EJB only implements the business logic; the services are associated through a deployment descriptor, which essentially acts as metadata for the EJB. At runtime, the container uses the metadata specified in the deployment descriptor to provide the services. The deployment descriptor is an XML file, not part of the Java classes that make up the EJBs. Is there a standard way to annotate the Java classes that make up the EJBs so that a developer can look at the class definition, together with annotations, and know everything about that class? It would be even better if the remote, home interfaces and the deployment descriptor could be automatically generated by a tool using the annotations. Better yet, can we provide the same kind of declarative services for a simple Java object? If so, how? This article examines how JSR-175: A Metadata Facility for the Java Programming Language will help us in finding answers to these questions and more.
Approaches to Programming
There are two approaches to programming called imperative programming and declarative programming. Imperative programming gives a list of instructions to execute in a particular order -- Java program that counts the number of words in a text file is an example of the imperative approach. Declarative programming describes a set of conditions, and lets the system figure out how to fulfill them. The SQL statement SELECT COUNT(*) FROM XYZ is an example for the declarative approach. In other words, "specifying how" describes imperative programming and "specifying what is to be done, not how" describes declarative programming.
Annotations
The Tiger release of Java (JDK 1.5) adds a new language construct called annotation (proposed by JSR-175). Annotation is a generic mechanism for associating metadata (declarative information) with program elements such as classes, methods, fields, parameters, local variables, and packages. The compiler can store the metadata in the class files. Later, the VM or other programs can look for the metadata to determine how to interact with the program elements or change their behavior.
Declaring an Annotation
Declaring an annotation is very simple -- it takes the form of an interface declaration with an @ preceding it and optionally marked with meta-annotations, as shown below:
package njunit.annotation;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface UnitTest {
String value();
} The Retention meta-annotation declares that the @UnitTest annotation should be stored in the class file and retained by the VM so it may be read reflectively. The Target meta-annotation declares that the @UnitTest annotation can be used to annotate methods in a Java class. @interface declares the @UnitTest annotation with one member called value, which returns a String.
Using an Annotation
Here is an example that shows how to use the @UnitTest annotation declared in the previous section:
import njunit.annotation.*;
public class Example {
@UnitTest(value="Test 1. This test will pass.")
public void pass() {
assert 10 > 5;
}
@UnitTest("Test 2. This test will fail.")
public void fail() {
assert 10 < 5;
}
} An annotation is applied to the code element by placing an annotation statement (@AnnotationType(...)) before the program element. Annotation values take the form "name=value"; for example, @UnitTest(value="some text"). Single-member annotations with a member named value are treated specially and can use the shorthand @UnitTest("some text"). In the example, the @UnitTest annotation is associated with the pass and fail methods.
Accessing Annotations at Runtime
Once annotations have been associated with program elements, we can use reflection to query their existence and get the values. The main reflection methods to query annotations are in a new interface: java.lang.reflect.AnnotatedElement.
Methods available in the AnnotatedElement interface are:
-
boolean isAnnotationPresent(Class annotationType)
Returnstrueif an annotation for the specified type is present on this element, elsefalse. This method is designed primarily for convenient access to marker annotations. -
T getAnnotation(Class annotationType)
Returns this element's annotation for the specified type if such an annotation is present, else null. -
Annotation[] getAnnotations()
Returns all annotations present on this element. (Returns an array of length zero if this element has no annotations.) -
Annotation[] getDeclaredAnnotations()
Returns all annotations that are directly present on this element. Unlike the other methods in this interface, this method ignores inherited annotations. (Returns an array of length zero if no annotations are directly present on this element.)
You may notice that the isAnnotationPresent and getAnnotation methods are defined using generics, another new feature available in JDK 1.5.
Here is the list of classes that implement the AnnotatedElement interface:
java.lang.reflect.AccessibleObjectjava.lang.Classjava.lang.reflect.Constructorjava.lang.reflect.Fieldjava.lang.reflect.Methodjava.lang.Package
Next, I'll show you an example that illustrates how to access annotations at runtime.
package njunit;
import java.lang.reflect.*;
import njunit.annotation.*;
public class TestRunner {
static void executeUnitTests(String className) {
try {
Object testObject =
Class.forName(className).newInstance();
Method [] methods =
testObject.getClass().getDeclaredMethods();
for(Method amethod : methods) {
UnitTest utAnnotation =
amethod.getAnnotation(UnitTest.class);
if(utAnnotation!=null) {
System.out.print(utAnnotation.value() +
" : " );
String result =
invoke(amethod, testObject);
System.out.println(result);
}
}
}catch(Exception x) {
x.printStackTrace();
}
}
static String invoke(Method m, Object o) {
String result = "passed";
try{
m.invoke(o,null);
} catch(Exception x) {
result = "failed";
}
return result;
}
public static void main(String [] args) {
executeUnitTests(args[0]);
}
} The TestRunner uses the @UnitTest annotation to determine whether a method is a unit test or not, invoke the method if it is marked with the @UnitTest annotation, and report the success or failure.
Here is how the TestRunner executes the unit test. Given a Java class, the TestRunner first obtains the list of all declared methods using reflection. Then it queries each method using the enhanced for construct and the getAnnotation method available in JDK 1.5 to find out whether it is marked as a @UnitTest. If it is marked, then it invokes the method and reports the success or failure. A test is considered failed if there is any exception when executing the test, and is considered passed otherwise.
In our Example class, the pass method will succeed when invoked, but the fail method will throw an AssertionError, which is propagated to the TestRunner.invoke method as InvocationTargetException.
When run with the command java -ea njunit.TestRunner Example, the output looks like the following:
Test 1. This test will pass. : passed
Test 2. This test will fail. : failed | | |
Meta-Annotations
Java defines several standard meta-annotations (annotation types designed for annotating annotation type declarations).
The new package java.lang.annotation contains the following meta-annotations:
| Meta-annotation | Purpose |
|---|---|
@Documented | Indicates that annotations with a type are to be documented by javadoc and similar tools by default. |
@Inherited | Indicates that an annotation type is automatically inherited. |
@Retention | Indicates how long annotations with the annotated type are to be retained. Example: @Retention(RetentionPolicy.RUNTIME) The enumeration RetentionPolicy defines the constants to be used for specifying Retention. |
@Target | Indicates the kinds of program element to which an annotation type is applicable. Example: @Target({ElementType.FIELD, ElementType.METHOD}) The enumeration ElementType defines constants that are used with the Target meta-annotation type to specify where it is legal to use an annotation type. |
Standard Annotations
There are two standard annotations in the java.lang package.
| Annotation | Purpose |
|---|---|
@Deprecated | Reincarnation of deprecated javadoc tag as an annotation in JDK 1.5. Compilers warn when a deprecated program element is used or overridden in non-deprecated code. |
@Overrides | Indicates that a method declaration is intended to override a method declaration in a super-class. If a method is annotated with this annotation type but does not override a super-class method, compilers are required to generate an error message. |
The following example illustrates the use of standard annotations.
public class Parent {
@Deprecated
public void foo(int x) {
System.out.println("Parent.foo(int x) called.");
}
}
public class Child extends Parent {
@Overrides
public void foo() {
System.out.println("Child.foo() called.");
}
} My intention is to extend the Parent class and override the foo(int x) method in Child class. By mistake, the foo method in the child does not override the one in the parent, because of the mismatch in the signature. Obviously, this is a bug. In the past, this kind of bug could be identified only at runtime after hours of debugging. Now, the use of the @Overrides annotation can save hours wasted in debugging. When a method is annotated with @Overrides, the compiler will check whether the method in a child class really overrides a method in the parent. The compiler will report an error when no method is overridden.
javac -source 1.5 Parent.java Child.java
Child.java:3: method does not override
a method from its superclass
@Overrides
^
1 error Let's correct the error by modifying the foo method signature, and compile the code again.
public class Child extends Parent{
@Overrides
public void foo(int x) {
System.out.println("Child.foo(int x) called.");
}
}
javac -Xlint:deprecation -source 1.5 Child.java
Child.java:4: warning:
[deprecation] foo(int) in Parent has been
deprecated
public void foo(int x) {
^
1 warning The foo method is marked as deprecated using the @Deprecated annotation, so the compiler reports a warning, as shown above.
A Complex Example
To keep the introduction simple, I used a single valued annotation. Now it's time to look at a complex one.
public @interface Trademark {
String description();
String owner();
} In the code snippet above we have declared an annotation called Trademark with two members: description and owner, both of which return String.
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.PACKAGE})
public @interface License {
String name();
String notice();
boolean redistributable();
Trademark[] trademarks();
} In the code snippet above, we have declared an annotation called License, which has members that return String, boolean, and an array of Trademark annotations. Now we can use the License annotation.
@License(
name = "Apache",
notice = "license notice ........",
redistributable = true,
trademarks =
{@Trademark(description="abcd",owner="xyz"),
@Trademark(description="efgh",owner="klmn")}
)
public class Example2 {
public static void main(String []args) {
License lic;
lic=Example2.class.getAnnotation(License.class);
System.out.println(lic.name());
System.out.println(lic.notice());
System.out.println(lic.redistributable());
Trademark [] tms = lic.trademarks();
for(Trademark tm : tms) {
System.out.println(tm.description());
System.out.println(tm.owner());
}
}
} The above example shows how to use annotations that have multiple members with String, boolean, and array return types. It also illustrates how to define annotations with parameter values that are annotations. The main method in Example2 illustrates how to access the annotations at runtime.
Defaults and Order of name=value Pairs
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface Help {
String topic() default "Unknown Topic";
String url();
} Default values for members can be specified in the annotation declaration so that it becomes optional when defining it. In the above example, String topic() default "Unknown Topic"; declares a default value for topic. While defining the Help annotation, the topic is optional and need not be specified. For example, @Help(url=".../help.html") is valid. The url must be specified, otherwise this will result in a compilation error.
In the annotation definition, the name=value pairs can be specified in any order. @Help(topic="Order does not matter", url=".../help.html") and @Help(url=".../help.html", topic="Order does not matter") are considered the same.
| | |
Package-Level Annotations
Annotations that can be applied to the package element are referred to as package-level annotations. An annotation with ElementType.PACKAGE as one of its targets is a package-level annotation. Package-level annotations are placed in a package-info.java file. This file should contain only the package statement, preceded by annotations. When the compiler encounters package-info.java file, it will create a synthetic interface, package-name.package-info. The interface is called synthetic because it is introduced by the compiler and does not have a corresponding construct in the source code. This synthetic interface makes it possible to access package-level annotations at runtime. The javadoc utility will use the package-info.java file if it is present, instead of package.html, to generate documentation.
The package-info.java file will look like this:
/**
* documentation comments...
*/
@Annotation1(...)
package sample; Note: The JDK 1.5 beta release compiler parses the package-info.java file, but does not emit a synthetic interface as stated in the specification.
Restrictions on Annotations
It is important to know that certain restrictions are imposed on annotation declaration:
- No
extendsclause is permitted. (Annotation types automatically extend a new marker interface,java.lang.annotation.Annotation.) - Methods must not have any parameters.
- Methods must not have any type parameters (in other words, generic methods are prohibited).
- Method return types are restricted to primitive types,
String,Class, enum types, annotation types, and arrays of the preceding types. - No
throwsclause is permitted. - Annotation types must not be parameterized.
Source-Level Annotations
Not all annotations need to be stored in the class files. For example, the deprecated javadoc tag used to mark a program element as obsolete and inform the compiler to emit a warning is now available as the Deprecated annotation, which is a source-level annotation. To declare an annotation to be visible only at source level, use @Retention(RetentionPolicy.SOURCE). The compiler does not store source-level annotations in the class file. Source-level annotations are expected to be used by tools such as documentation generators (javadoc), compilers, and other tools that require/have access to source files.
Accessing Annotations in the Source Files
We can use the Doclet API to access annotations from the source files. The com.sun.javadoc package provides several new interfaces, and methods have been added to existing interfaces to support annotations. I'll walk you through an example that shows you how to access annotations using doclets.
import com.sun.javadoc.*;
public class ListAnnotations {
public static boolean start(RootDoc root) {
ClassDoc[] classes = root.classes();
for (ClassDoc clsDoc : classes) {
processAClass(clsDoc);
}
return true;
}
static void processAClass(ClassDoc clsDoc) {
System.out.println("List of annotations in " +
clsDoc.name());
list(clsDoc.annotations());
}
static void list(AnnotationDesc[] annDescs) {
for (AnnotationDesc ad : annDescs) {
AnnotationTypeDoc at = ad.annotationType();
System.out.println("----------");
System.out.println("Annotation : " + at.name());
AnnotationDesc.MemberValuePair [] members =
ad.memberValues();
for(AnnotationDesc.MemberValuePair mvp : members) {
System.out.println("Member = " +
mvp.member().name() +
", Value = "+ mvp.value() + "");
}
}
}
} A Java class with the method public static boolean start(com.sun.javadoc.RootDoc root) is a doclet. The doclet uses the interfaces from the com.sun.javadoc package to gain access to various elements of a class from the source file. To execute a doclet, we have to use the javadoc tool. javadoc will parse the source files and call the start method, which is the entry point for a doclet, similar to the main method in a Java program.
Compiling and Executing the Doclet
javac -source 1.5 -cp c:\jdk15\lib\tools.jar ListAnnotations.java
javadoc -source 1.5 -doclet ListAnnotations -sourcepath . UnitTest.java
Loading source file UnitTest.java...
Constructing Javadoc information...
List of annotations in UnitTest
----------
Annotation : Retention
Member = value, Value = RUNTIME
----------
Annotation : Target
Member = value, Value = METHOD Class-Level Annotations
We already saw two kinds of annotations: runtime and source. There is yet another kind of annotation: class. This is the default when the Retention meta-annotation is not present or it is present with a value RetentionPolicy.CLASS; the compiler stores annotations in the class files but the VM may not load them at runtime, so they may not be available for reflective access.
Attributes in .NET Vs. Annotations in Java
Microsoft's .NET CLR supports a feature called attributes, which is similar to annotations in Java. Let us see the similarities and differences between attributes and annotations.
| .NET Attributes | Java Annotations |
|---|---|
Attributes are classes that should extend the System.Attribute class. | Annotations are interfaces that automatically extend the java.lang.annotation.Annotation interface. |
Types of an attribute parameter must be primitive types, object, System.Type, enum types, or arrays of the preceding types. | Method return types are restricted to primitive types, String, Class, enum types, annotation types, and arrays of the preceding types. |
Attribute parameters can be named or positional. Named ("name=value") parameters can be in any order. | Supports only named ("name=value") parameters and can be in any order. Single member annotations follow the naming convention for the member type as value; can use shorthand. |
| Attributes can be applied to assembly, class, constructor, delegate, enum, event, field, interface, method, module, parameter, property, return value, and struct. | Annotations can be applied to annotation, class, constructor, enum, field (includes enum constants), interface, local variable, method, parameter, and package. |
| A declaration can have multiple attributes for the same attribute type. | A declaration cannot have multiple annotations for the same annotation type. |
| Attributes are always stored in the assembly and available at runtime. | Annotations marked with @Target(RetentionPolicy. SOURCE) meta-annotation (referred to as source-level annotations) are not stored in the class files and will not be available at runtime. |
| All attributes can be accessed at runtime using reflective APIs. | Annotations marked with @Target(RetentionPolicy.RUNTIME) meta-annotation (referred to as runtime annotations) can be accessed at runtime through reflective APIs. |
| System.CodeDOM APIs for working with attributes in source files. | Doclet API provides limited support for working with annotations at source files. |
| .NET provides standard attributes for security, transactions, language interoperability, COM integration, COM+ hosting, marshalling, serialization, components and controls, assemblies and packaging, threading, XML and web services. | Several new JSRs are in progress to define standard annotations for web services and others. |
| Context attributes provide an interception mechanism that can preprocess and postprocess class instantiation and method calls. | N/A |
For developers familiar with .NET attributes, the JDK 1.5 implementation of annotations may appear to be a limitation, but it is not. Java annotations can be used to define design-time information, such as documentation or instructions to the compiler; runtime information, such as tagging a method as a unit test; or behavioral characteristics, such as whether a member is participating in a transaction or not, similar to how attributes are used in .NET applications. Although there is no standard interception mechanism like .NET's context attributes in Java yet, AOP frameworks such as AspectJ and JBossAOP provide call interception mechanisms, and these frameworks may be reimplemented to take advantage of annotations.
Annotations in the Pre-JDK 1.5 World
In older versions of Java, javadoc custom tags are used as annotations. Many popular open source design-time tools, such as XDoclet, EJBGen, and others, generate code based on javadoc tags form the source files. Open source projects like Jakarta Commons Attributes and Attrib4j use javadoc tags to associate custom metadata and make it available at runtime. In both Commons Attributes and Attrib4j, attributes are classes more like .NET attributes, whereas JDK 1.5 treats them as interfaces. For those who can't start using JDK 1.5 as soon as the production release of Tiger is available, it's worthwhile to take a look at Retroweaver. Retroweaver transforms JDK 1.5 classes into classes that can run on older VMs; this way, you can start using JDK 1.5 features with an older version of the JRE.
Conclusion
Every new release of Java has introduced new features, but few warrant a new way of thinking to realize their full potential. Using annotations effectively to simplify programming in Java requires a shift in our thought processes. Even though we use declarative programming languages such as SQL and XSLT most frequently, it may take some time for us to understand how to use declarative and imperative programming together.
Here are a few things you could do with annotations to simplify or empower your programming:
- Develop code generators using annotations.
- Develop a new unit-testing framework using annotations, such as NUnit.
- Think about ways to extend the compiler using custom annotation handlers.
- Think about annotation's role in defining AOP extensions to Java.
Once JSRs like JSR-181: Web Services Metadata for the Java Platform and others are implemented, we will be able to appreciate the productivity gained by using annotations.
In the near future, we will see a number of existing frameworks being reimplemented using annotations, generics and other new features available in JDK 1.5, codenamed Tiger. So get ready to meet the Tiger.
(http://www.onjava.com/lpt/a/4768)
J2SE 5.0 in a Nutshell by Calvin Austin
Java 2 Platform Standard Edition (J2SE) 5.0 ("Tiger") is the next major revision to the Java platform and language; it is currently slated to contain 15 component JSRs with nearly 100 other significant updates developed through the Java Community Process (JCP).
NOTE: The external version number of this release is 5.0 and its internal version number is 1.5.0, as described at J2SE Naming and Versioning.
With so many exciting changes in this release, you may be wondering where you should start. As in previous releases, the comprehensive list of all changes is available in the Release notes guide. This article, from the J2SE team, will take you through the major changes so that you have a grasp of what J2SE 5.0 has to offer, before diving into the API docs.
The J2SE 5.0 release is focused along certain key themes:
There are a small number of features that are just as important but didn't neatly fit in with the themes; they are listed at the end:
Ease of Development
You may have already seen reports about some of the new Java Language changes that comprise the Ease of Development theme. The changes include generic types, metadata, autoboxing, an enhanced for loop, enumerated types, static import, C style formatted input/output, variable arguments, concurrency utilities, and simpler RMI interface generation.
JSR-201 contains four of these language changes; enhanced for loop, enumerated types, static import and autoboxing; JSR-175 specifies the new metadata functionality, while JSR-14 details generic types.
The new default language specification implemented by the javac compiler is version 5.0, also known as 1.5, so you do not need to supply the option -source 1.5 (as required in beta1).
Metadata
The metadata feature in J2SE 5.0 provides the ability to associate additional data alongside Java classes, interfaces, methods, and fields. This additional data, or annotation, can be read by the javac compiler or other tools, and depending on configuration can also be stored in the class file and can be discovered at runtime using the Java reflection API.
One of the primary reasons for adding metadata to the Java platform is to enable development and runtime tools to have a common infrastructure and so reduce the effort required for programming and deployment. A tool could use the metadata information to generate additional source code, or to provide additional information when debugging.
In beta2 we are pleased to announce the availability of an annotation processing tool called apt. Apt includes a set of new reflective APIs and supporting infrastructure to process program annotations. The apt reflective APIs provide a build-time, source-based, read-only view of program structure which cleanly models the Java programming language's type system. First, apt runs annotation processors that can produce new source code and other files. Next, apt can cause compilation of both original and generated source files, easing development. For more information on apt refer to the apt guide.
In the following example code you can additionally create an AnnotationFactory processor for apt to generate code or documentation when finding the debug annotation tag.
import java.lang.annotation.*; |
With a metadata processing tool, many repetitive coding steps could be reduced to a concise metadata tag. For example, the remote interface required when accessing a JAX-RPC service implementation could be implemented as follows:
Before
public interface PingIF extends Remote { |
After
public class Ping { |
Generic Types
Generic types have been widely anticipated by the Java Community and are now part of J2SE 5.0. One of the first places to see generic types in action is the Collections API. The Collections API provides common functionality like LinkedLists, ArrayLists and HashMaps that can be used by more than one Java type. The next example uses the 1.4.2 libraries and the default javac compile mode.
ArrayList list = new ArrayList(); |
The cast to Integer on the last line is an example of the typecasting issues that generic types aim to prevent. The issue is that the 1.4.2 Collection API uses the Object class to store the Collection objects, which means that it cannot pick up type mismatches at compile time. The first notification of a problem is a ClassCastException at runtime.
The same example with the generified Collections library is written as follows:
ArrayList |
The user of a generified API has to simply declare the type used at compile type using the <> notation. No casts are needed and in this example trying to add a String object to an Integer typed collection would be caught at compile time.
Generic types therefore enable an API designer to provide common functionality that can be used with multiple data types and which also can be checked for type safety at compile time.
Designing your own Generic APIs is a little more complex that simply using them. To get started look at the java.util.Collection source and also the API guide.
Autoboxing and Auto-Unboxing of Primitive Types
Converting between primitive types, like int, boolean, and their equivalent Object-based counterparts like Integer and Boolean, can require unnecessary amounts of extra coding, especially if the conversion is only needed for a method call to the Collections API, for example.
The autoboxing and auto-unboxing of Java primitives produces code that is more concise and easier to follow. In the next example an int is being stored and then retrieved from an ArrayList. The 5.0 version leaves the conversion required to transition to an Integer and back to the compiler.
Before
ArrayList |
After
ArrayList |
Enhanced for Loop
The Iterator class is used heavily by the Collections API. It provides the mechanism to navigate sequentially through a Collection. The new enhanced for loop can replace the iterator when simply traversing through a Collection as follows. The compiler generates the looping code necessary and with generic types no additional casting is required.
Before
ArrayList |
After
ArrayList |
Enumerated Types
This type provides enumerated type when compared to using static final constants. If you have previously used the identifier enum in your own application, you will need to adjust the source when compiling with javac -source 1.5 (or its synonym -source 5).
public enum StopLight { red, amber, green }; |
Static Import
The static import feature, implemented as "import static", enables you to refer to static constants from a class without needing to inherit from it. Instead of BorderLayout.CENTER each time we add a component, we can simply refer to CENTER.
import static java.awt.BorderLayout.*; |
Formatted Output
Developers now have the option of using printf-type functionality to generate formatted output. This will help migrate legacy C applications, as the same text layout can be preserved with little or no change.
Most of the common C printf formatters are available, and in addition some Java classes like Date and BigInteger also have formatting rules. See the java.util.Formatter class for more information. Although the standard UNIX newline '\n' character is accepted, for cross-platform support of newlines the Java %n is recommended.
System.out.printf("name count%n"); |
Formatted Input
The scanner API provides basic input functionality for reading data from the system console or any data stream. The following example reads a String from standard input and expects a following int value.
The Scanner methods like next and nextInt will block if no data is available. If you need to process more complex input, then there are also pattern-matching algorithms, available from the java.util.Formatter class.
Scanner s= new Scanner(System.in); |
Varargs
The varargs functionality allows multiple arguments to be passed as parameters to methods. It requires the simple ... notation for the method that accepts the argument list and is used to implement the flexible number of arguments required for printf.
void argtest(Object ... args) { |
Concurrency Utilities
The concurrency utility library, led by Doug Lea in JSR-166, is a special release of the popular concurrency package into the J2SE 5.0 platform. It provides powerful, high-level thread constructs, including executors, which are a thread task framework, thread safe queues, Timers, locks (including atomic ones), and other synchronization primitives.
One such lock is the well known semaphore. A semaphore can be used in the same way that wait is used now, to restrict access to a block of code. Semaphores are more flexible and can also allow a number of concurrent threads access, as well as allow you to test a lock before acquiring it. The following example uses just one semaphore, also known as a binary semaphore. See the java.util.concurrent package for more information.
final private Semaphore s= new Semaphore(1, true); |
rmic -- The RMI Compiler
You no longer need to use rmic, the rmi compiler tool, to generate most remote interface stubs. The introduction of dynamic proxies means that the information normally provided by the stubs can be discovered at runtime. See the RMI release notes for more information.
Scalability and Performance
The 5.0 release promises improvements in scalability and performance, with a new emphasis on startup time and memory footprint, to make it easier to deploy applications running at top speed.
One of the more significant updates is the introduction of class data sharing in the HotSpot JVM. This technology not only shares read-only data between multiple running JVMs, but also improves startup time, as core JVM classes are pre-packed.
Performance ergonomics are a new feature in J2SE 5.0. This means that if you have been using specialized JVM runtime options in previous releases, it may be worth re-validating your performance with no or minimal options.
Monitoring and Manageability
Monitoring and Manageability is a key component of RAS (Reliability, Availability, Serviceability) in the Java platform.
The J2SE 5.0 release provides comprehensive monitoring and management support: instrumentation to observe the Java virtual machine, Java Management Extensions (JMX) framework, and remote access protocols. All this is ready to be used out-of-the-box. (See the Management and Monitoring release notes for more details.)
The JVM Monitoring & Management API specifies a comprehensive set of instrumentation of JVM internals to allow a running JVM to monitored. This information is accessed through JMX (JSR-003) MBeans and can accessed locally within the Java address space or remotely using the JMX remote interface (JSR-160) and through industry-standard SNMP tools.
One of the most useful features is a low memory detector. JMX MBeans can notify registered listeners when the threshold is crossed, see javax.management and java.lang.management for details.
J2SE 5.0 provides an easy way to enable out-of-the-box remote management of JVM and an application (see Out-of-the-Box for details). For example, to start an application to be monitorable by jconsole in the same local machine, use the following system property:
java -Dcom.sun.management.jmxremote -jar Java2Demo.jar |
and to monitor it remotely through JMX without authentication:
java -Dcom.sun.management.jmxremote.port=5001 |
For an idea of how easy the new API is to use, the following reports the detailed usage of the memory heaps in the HotSpot JVM.
import java.lang.management.*; |
New JVM Profiling API (JSR-163)
The release also contains a more powerful native profiling API called JVMTI. This API has been specified through JSR-163 and was motivated by the need for an improved profiling interface. However, JVMTI is intended to cover the full range of native in-process tools access, which in addition to profiling, includes monitoring, debugging and a potentially wide variety of other code analysis tools.
The implementation includes a mechanism for bytecode instrumentation, Java Programming Language Instrumentation Services (JPLIS). This enables analysis tools to add additional profiling only where it is needed. The advantage of this technique is that it allows more focused analysis and limits the interference of the profiling tools on the running JVM. The instrumentation can even be dynamically generated at runtime, as well as at class loading time, and pre-processed as class files.
The following example creates an instrumentation hook that can load a modified version of the class file from disk. To run this test, start the JRE with java -javaagent:myBCI BCITest
//File myBCI.java |
Improved Diagnostic Ability
Generating Stack traces has been awkward if no console window has been available. Two new APIs, getStackTrace and Thread.getAllStackTraces provide this information programmatically.
StackTraceElement e[]=Thread.currentThread().getStackTrace(); |
The HotSpot JVM includes a fatal error handler that can run a user-supplied script or program if the JVM aborts. A debug tool can also connect to a hung JVM or core file using the HotSpot JVM serviceability agent connector.
-XX:OnError="command" |
Desktop Client
The Java Desktop client remains a key component of the Java platform and as such has been the focus of many improvements in J2SE 5.0.
This Beta release contains some of the early improvements in startup time and memory footprint. Not only is the release faster, but the Swing toolkit enjoys a fresh new theme called Ocean. And by building on the updates in J2SE 1.4.2, there are further improvements in the GTK skinnable Look and Feel and the Windows XP Look and Feel.
Linux and Solaris users, and new in beta2, Windows users, who have the latest OpenGL drivers and select graphic cards can get native hardware acceleration from Java2D using the following runtime property:
java -Dsun.java2d.opengl=true -jar Java2D.jar |
The Linux release also has the fast X11 toolkit, called XAWT, enabled by default. If you need to compare against the motif version you can use the following system property:
java -Dawt.toolkit=sun.awt.motif.MToolkit -jar Notepad.jar |
(the X11 toolkit is called sun.awt.X11.XToolkit)
The X11 Toolkit also uses the XDnD protocol so you can drag-and-drop simple components between Java and other applications like StarOffice or Mozilla.
Miscellaneous Features
Core XML Support
J2SE 5.0 introduces several revisions to the core XML platform, including XML 1.1 with Namespaces, XML Schema, SAX 2.0.2, DOM Level 3 Support and XSLT with a fast XLSTC compiler.
In addition to the core XML support, future versions of the Java Web Services Developer Pack will deliver the latest web services standards: JAX-RPC & SAAJ (WSDL/SOAP), JAXB, XML Encryption, and Digital Signature and JAXR for registries.
Supplementary Character Support
32-bit supplementary character support has been carefully added to the platform as part of the transition to Unicode 4.0 support. Supplementary characters are encoded as a special pair of UTF16 values to generate a different character, or codepoint. A surrogate pair is a combination of a high UTF16 value and a following low UTF16 value. The high and low values are from a special range of UTF16 values.
In general, when using a String or sequence of characters, the core API libraries will transparently handle the new supplementary characters for you. However, as the Java "char" still remains at 16 bits, the very few methods that used char as an argument now have complementary methods that can accept an int value which can represent the new larger values. The Character class in particular has additional methods to retrieve the current character and the following character in order to retrieve the supplementary codepoint value as below:
String u="\uD840\uDC08"; |
See the Unicode section in Character for more details.
JDBC RowSets
There are five new JDBC RowSet class implementations in this release. Two of the most valuable ones are CachedRowSet and WebRowSet. RowSet objects, unlike ResultSet objects, can operate without always being connected to a database or other data source. Without the expensive overhead of maintaining a connection to a data source, they are much more lightweight than a ResultSet object. The CachedRowSet contains an in-memory collection of rows retrieved from the database that can, if needed, be synchronized at a later point in time. The WebRowSet implementation, in addition, can write and read the RowSet in XML format.
The following code fragment shows how easy it is to create and use a WebRowSet object.
Class.forName("org.postgresql.Driver"); |
References
New Language Features for Ease of Development in the Java 2 Platform Standard Edition 5.0: http://java.sun.com/features/2003/05/bloch_qa.html
Tiger Component JSRs
003 Java Management Extensions (JMX) Specification http://jcp.org/en/jsr/detail?id=3
013 Decimal Arithmetic Enhancement http://jcp.org/en/jsr/detail?id=13
014 Add Generic Types To The Java Programming Language http://jcp.org/en/jsr/detail?id=14
028 Java SASL Specification http://jcp.org/en/jsr/detail?id=28
114 JDBC Rowset Implementations http://jcp.org/en/jsr/detail?id=114
133 Java Memory Model and Thread Specification Revision http://jcp.org/en/jsr/detail?id=133
160 Java Management Extensions (JMX) Remote API 1.0 http://jcp.org/en/jsr/detail?id=160
163 Java Platform Profiling Architecture http://jcp.org/en/jsr/detail?id=163
166 Concurrency Utilities http://jcp.org/en/jsr/detail?id=166
174 Monitoring and Management Specification for the Java Virtual Machine http://jcp.org/en/jsr/detail?id=174
175 A Metadata Facility for the Java Programming Language http://jcp.org/en/jsr/detail?id=175
200 Network Transfer Format for Java Archives http://jcp.org/en/jsr/detail?id=200
201 Extending the Java Programming Language with Enumerations, Autoboxing, Enhanced for Loops and Static Import http://jcp.org/en/jsr/detail?id=201
204 Unicode Supplementary Character Support http://jcp.org/en/jsr/detail?id=204
206 Java API for XML Processing (JAXP) 1.3 http://jcp.org/en/jsr/detail?id=206







