Java 5 6 Generics, Concurrency, Garbage Collection, Tuning

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

0 comments

Post a comment

    Post a comment
    Embed Video
    Edit your comment Cancel

    Notes on slide 1

    The agenda will cover all aspects of the new J2SE 5 product - First we'll examine some of the motivations for the design of J2SE 5 and the main themes used - We will look at the big changes to the Java language, something that has changed little until Tiger. We'll go into the technical details of generics and metadata to help you understand how to get the most from these features - J2SE 5 has a lot of new library features. We won't go over all of these because of time constraints, but will focus mostly on the new concurrency utilities that greatly simplify writing multi-threaded applications and gove the programmer a wealth of choice on how to do this. - We'll look at the changes that have been made at the virtual machine level, seeing how the VM is easier to configure to achieve optimal performance and the new monitoring and manageability features for enterprise deployments. - At the end we'll sum up and provide you with links to places where you can get more detailed information.

    The main design themes for J2SE 5 were: quality, stability and compatability: Java is used extensively in enterprise, mission critical applications. Customers want a product that is rock solid and will run without problems for as long as they need. Since there are a number of fundamental changes in this release we've been very careful to ensure that moving to J2SE 5 is as painless as possible for existing applications. We don't want people to have to do lots of porting to get their applications running. Java is truly write once, run anywhere and it's important that Java can fully support every typre of environment from desktop to data centre. We've put a lot of effort into ensuring that the desktop is not neglected and applications can be written that fully fit into the native windowing environment and have performance almost as good (if not better) than native applications. Since Java is so popular for server applications Sun have also put more effort into ensuring that the algorithms used within the VM for things like memory management and threads will scale to the biggest machines that money can buy. People are always asking for more features in Java and Sun have tried to address as many of those as they can and which make sense. Since compatability and portability are such basic foundations of Java Sun have been very careful to introduce these new features in an evolutionary rather than revolutionary way. Finally, probably the biggest single motivation for many of the changes in J2SE 5 was the idea of making Java easier to develop. Java is a third generation language and requires good programming skills to use effectively. As you'll see many of the new features are designed to make programming easier and the end result less prone to errors

    Here we see a brief history of the Java language, showing the changes that have been made over time As we all know Java was launched in 1995 and has become a very popular language for developement of all types of applications. As with any new language, developers pretty soon found that there were some things that needed to be fine tuned. Java was lucky in that the 1.1 release only introduced relatively minor changes: the ability to create inner classes and the new event model that would scale much better than the old version. In JDK 1.2 and 1.3 there were no changes to the language; many new classes were added and a lot of work was done on the performance of the VM but the language remained the same. In JDK1.4 a minor change was made by introducing assertions. With the launch of JDK 5.0 we're seeing the biggest changes to the Java language since its launch, and we don't just mean in terms of the version number.

    Unfortunately, there aren't many benchmarks that span back to the beginning of Java. This one, (named Volano) probably isn't the best as a general purpose benchmark either. But the improvement is dramatic: 7 times better performance since 1.2.2. But this doesn't tell the whole story: The Java platform has gotten better, and this benchmark doesn't take advantage of that!

    Now let's spend sometime talking abut Java SE 5 Features

    Let's start then by looking at the new features included at the language level in J2SE 5

    This slide lists the seven new key features in J2SE 5. We'll describe each of these features. For generics and metadata we're going to go into a lot of detail to help you understand all of the issues around using these features correctly and effectively.

    Generics is a feature that has been requested many times in Java. Sun have had to be very careful about how to introduce this feature in a way that minimises the impact of compatability. As we'll see generics is a rather bad name for this feature since what we're really doing is allowing classes to be made type specific rather than type generic (which is really the situation that we have had all along in Java).

    OK, Lets take a look at Pre Java SE 5.0 code here. Can anyone tell if there is a problem here. Is it a compile time problem or a runtime problem? What problem? => Runtime exception

    This piece of code illustrates the problem in Java that generics addresses. A programmer has created a method called expurgate that takes a collection and removes all strings who's length is four characters from it. The method takes a Collection as a parameter and then iterates through all of the elements looking for four character strings. The Collection can hold objects of any type (meaning strictly speaking that it is generic - see the naming problem?) When we extract an element from the collection we need to do an explicit cast to tell the compiler the type of the object we're getting. This is dangerous, as we can see. A different programmer creates a Vector and rather than adding a String, adds an Integer object. This all compiles fine, as Integer is still a sub-class of Object which is the type of the argument for the add method. However, at run time when the code calls expurgate the VM will throw a ClassCastException since the Integer object is not a String or sub-type of String. This is bad because it is a runtime exception. This code could be running in a telco billing application where runtime exceptions mean potentially large loss of revenue. What we need is a way to tell the compiler, not the VM what type the collection is so that the compiler can check all uses and report an error when the code is compiled, not when it's running. This is what generics do.

    To restate the problem, the issue is that the compiler cannot check the types of the objects being stored in a collection because it has no way of knowing the type of the object, other than that it will be an Object or sub-type, which all classes by default are. All assignments when using the collections must do an explicit cast and can generate a runtime ClassCastException. The solution is for the programmer to give an explicit typing to a collection (or other class where this is required). By doing that the compiler can now check that all items added to a typed collection are correct. If we try to add an Integer to a String typed collection we will get a compiler error telling us that it is an inappropriate type. We can make the changes and prevent a runtime exception. The implementation of this feature is only in terms of compilation. The compiler is effectively adding the explicit cast for you and ensuring that only the correct type of obejcts are added. This is a key point from the perspective of compatability, which we'll discuss in more detail later. This is guaranteed to succeed from the point of view of eliminating ClassCastExceptions caused by this type of error. The asterisk is there because this will only hold true if all the code of an application is recompiled using the J2SE 5 compiler, so that all references can be checked. Pre 5.0 class files will still run using the new JVM. If you mix old and new class files you could still get a ClassCastException since the compiler will have been unable to check that the type of object being added to a collection is correct.

    In J2SE 5 all the collection classes (as well as many others) have been made generic. Here we look at the same example we had earlier that would have thrown a ClassCastException. Using generics, when we instantiate the Vector class we also include a type argument to tell the compiler that the Vector is only to be used to hold objects of type String (String is final so it's not possible to use a sub-class). If we then try and call the add method with an Integer object as a parameter the compiler will know this is wrong and will report an error. Lets declare another Vector, this time parameterised for Integer objects. If we return the comparison between the two Vectors what will the result be, true or false? The answer is true. The base type of the objects is still the same, they are both Vector and they both share the same class at runtime. The fact that one has been typed to hold Strings and one has been typed to hold Integers does not affect this comparison. This is an important fact to remember as we'll see later when we discuss type erasure.

    Well of course you all know that I wouldn't ask if the answer was yes. The problem is that A collection with the type argument of Objects is NOT a supertype of all types of collection. If you try to call this method and pass in a collection with type argument String you will get a compiler error due to the type mismatch. How do we therefore solve this problem? Invariant sub-typing: Collection is not a super-class of Collection Remember earlier when we saw the comparison of the two references? The base types are the same, but parameters do not have inheritance in the same way as concrete classes.

    The answer is using what is called a wildcard type argument. This is the question mark that we saw earlier in the syntax definition for type arguments. The wildcard type is equivalent to saying the type is unknown, so Collection<?> is the same as saying a Collection of unknown type. This is also something important to remember as we'll see shortly

    There may be situations where we want to be able to define a type argument so that it is restricted to a particular class or sub-type of that class. Unlike normal classes, parameterised types do not have inheritance - we saw this earlier where a Collection of type String could not be treated as a sub-class of Collection of type Object. In this example we want to define a method that can draw a set of shapes taken from a List. Since we have a good OO design let's say we've defined an interface called Shape which has concrete implementations called Circle and Triangle. If we defined the drawAll() method to take a List of type Shape we'd get compiler errors trying to pass a List of Circle or Triangle objects.. We could use the wildcard type, but then we could pass any List to the method including ones that did not contain Shape objects. What we need to do is use a bounded wildcard, which is what we do here. We still use the wildcard type but we also specify that it extends Shape. This means that only a List typed to contain objects that are a sub-class of Shape can be passed as a parameter (remember that Shape is a sub-class of itself). Our example will compile and work as we want it to do.

    Generics is a feature that has been requested many times in Java. Sun have had to be very careful about how to introduce this feature in a way that minimises the impact of compatability. As we'll see generics is a rather bad name for this feature since what we're really doing is allowing classes to be made type specific rather than type generic (which is really the situation that we have had all along in Java).

    The first feature is what's called autoboxing and unboxing. Java is an object oriented language, but to purist like Smalltalk developers it's not truly object oriented as it still has primitive types to represent numbers and booleans. The reason for including these is that if everything is treated as an object you will never be able to get the application to perform as well as natively compiled C and C++ code. The problem with primitives is that in order to store them in a collection they have to be made into an object. Java provides the wrapper classes like Integer and Short for this purpose. To add a primitive to a collection is therefore complex as we must first instantiate a new wrapper class object and then add it to the collection. Similarly when getting the value out of the collection we first must retrieve the wrapper object and then call the appropriate method. Auto-boxing and unboxing solves this problem by letting the compiler do the hard work for us. As we can see in the example we can simply assign the value 22 to the Byte wrapper class object. The compiler will instantiate the object for us. We can do this because Java does not support explicit pointers. In C or C++ we wouldn't know whether this was assigning the memory address 22 to this object reference. Since in Java you cannot do that, the compiler knows it must be an auto-boxing conversion. Similarly when we want to get the value back we simply say int i = byteObj and the compiler fills in the method call for us. This will also work in method calls so we can simply pass the value 22 to the add method of ArrayList and the compiler will replace that with add(new Integer(22)).

    The first feature is what's called autoboxing and unboxing. Java is an object oriented language, but to purist like Smalltalk developers it's not truly object oriented as it still has primitive types to represent numbers and booleans. The reason for including these is that if everything is treated as an object you will never be able to get the application to perform as well as natively compiled C and C++ code. The problem with primitives is that in order to store them in a collection they have to be made into an object. Java provides the wrapper classes like Integer and Short for this purpose. To add a primitive to a collection is therefore complex as we must first instantiate a new wrapper class object and then add it to the collection. Similarly when getting the value out of the collection we first must retrieve the wrapper object and then call the appropriate method. Auto-boxing and unboxing solves this problem by letting the compiler do the hard work for us. As we can see in the example we can simply assign the value 22 to the Byte wrapper class object. The compiler will instantiate the object for us. We can do this because Java does not support explicit pointers. In C or C++ we wouldn't know whether this was assigning the memory address 22 to this object reference. Since in Java you cannot do that, the compiler knows it must be an auto-boxing conversion. Similarly when we want to get the value back we simply say int i = byteObj and the compiler fills in the method call for us. This will also work in method calls so we can simply pass the value 22 to the add method of ArrayList and the compiler will replace that with add(new Integer(22)).

    Generics is a feature that has been requested many times in Java. Sun have had to be very careful about how to introduce this feature in a way that minimises the impact of compatability. As we'll see generics is a rather bad name for this feature since what we're really doing is allowing classes to be made type specific rather than type generic (which is really the situation that we have had all along in Java).

    The next new feature is the enhanced for loop, If we have a collection and want to iterate over all the elements we use a for loop and an Iterator object. This is potentally error prone as the for loop has three parts to it initialisation, test and increment. The iterator can be used in all three of these places; if cut and paste is used incorrectly or an identifier is mis-typed some very subtle and hard to find bugs can be introduced. The solution is to let the compiler do the hard work for you again. To do this, the for loop has had a new syntactical construct added. Rather than using the traditional three statements separated by semi-colons, we have a single statement of the form variable defintiion colon collection name. This tells the compiler that we want to iterate over the collection specified and will use the variable identifier within the loop to reference each item. This sytax will work either for a collection or for an array.

    Here we see a good example of old and new style programming. We have a method that is designed to cancel a set of timer tasks. In the old code we would need to retrieve the Iterator from the collection passed as a parameter, which is the initialisation of the for loop. The test of the for loop uses the hasNext method of the iterator and then within the body of the foor loop we use the next method to retrieve the element. We also need to do an explicit cast so that the object retrieved from the collection can be assigned to the correct type. Obvioulsy, this is rather verbose and prone to errors when using the same Iterator three times. The new code makes this much simpler. We simply use the new for loop construct to define a variable, task that will be used in the body of the for loop, being of type TimerTask and iterating over the collection passed in, c. We then simply call the cancel method on task. We're also using generics in this example to tell the compiler the type of the collection.

    Generics is a feature that has been requested many times in Java. Sun have had to be very careful about how to introduce this feature in a way that minimises the impact of compatability. As we'll see generics is a rather bad name for this feature since what we're really doing is allowing classes to be made type specific rather than type generic (which is really the situation that we have had all along in Java).

    Often there are times when a programmer wants to have a variable that can only hold one of a fixed set of values. Typically we do this by assigning a number to each value and then storing it as an integer, using final static defintitions to assign the appropriate values. This is not a reliable mechanism which is why J2SE has introduced type safe enumerations. An enumeration is a new kind of class definition which uses the keyword enum to differentiate it from a normal class. Even though an enumeration is like a class in many way, it is not the same. You cannot instantiate an enumeration; this is effectively done once by the VM when the system. The definition of an enumeration contains a set of public, self-typed members which are used as the constants of that type. These values can be used in a switch statement with the case keyword. Previously all values used with a case statement had to be integers.(Sang: so you can do swtich statement with a typed object?) The compiler will handle the use of the enumeration correctly. With the introduction of enumerations Java now has a new reserved word, enum. This is a consideration from a migration perspective since any code using enum as an identifier will need to be changed to compile under J2SE 5.

    First example of the use of an enumeration. This code uses two simple enumerations to represent the cards in a pack. One enumeration is used for the suits and one is used for the values. The definition is very simple, we just define the enumeration as having the constants we want separated by commas. We can then refer to these constants in our program, for example in a switch statement. For this example we create an ArrayList to hold the pack of cards. We use a type argument to tell the compiler that we want this List to only hold objects of type Card (which is defined elsewhere). We can then use the new for loop construct to iterate over the enumerations, populating the list. Notice the use of the values() method to return a collection of the constants of the enumeration. Finally we shuiffle the deck using the shuffle() utility method of the Collections class. Using a combination of features from J2SE 5 we can see that code can become much more concise, easy to read and easy to maintain. Imagine writing this code in pre J2SE 5 Java; it would take 3 or 4 times as much code

    .

    Generics is a feature that has been requested many times in Java. Sun have had to be very careful about how to introduce this feature in a way that minimises the impact of compatability. As we'll see generics is a rather bad name for this feature since what we're really doing is allowing classes to be made type specific rather than type generic (which is really the situation that we have had all along in Java).

    Java has always supported import declarations that allow types from other packages to be referred to using their simple names, i.e. without using a fully qualified class name. However, the static members of classes have not been treated in the same way; for example, whenever you refer to a static member of the Color class it's necessary to explicitly state Color.yellow or Color.blue. In J2SE 5 the import mechanism has been extended to include static members. To use this the static keyword is added to the normal import to indicate that static members can be accessed without specifying the class name. As with normal imports the wildcard * can be used to indicate all members of the package. The import applies to all static members of the class including methods and enums.

    Lets look at some of the changes and new features in the Java Virtual Machine

    Now that Java supports varargs, the much loved (or maligned) printf library call has been added that will be familiar to C and C++ programmers. If you have not used these languages before you will want to have a look at the manual page to see exactly how to use this. printf takes a string as an argument that will be displayed on the standard output. This string can contain arguments identified by the % character that will be replaced by the values of the other arguments when the string is displayed. The order of the arguments in the string must match the order of the arguments in the method call. The % character is followed by characters to indicate what type the argument is and how it should be formatted for display. For example, %s indicates a free format string; %2.2F indicates a floating point number that should have two digits before and after the decimal point. Since Java is cross platform you can use %n to specify a newline that will be correct for the current OS.
    and
    can still be used, but these will only output carriage return and linefeed. The scanf function that is the inverse of printf has not been included. The Scanner class provides a simple text scanner which can parse primitive types and strings using regular expressions. A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace. The resulting tokens may then be converted into values of different types using the various next methods. In the example shown, the code allows a user to read a number from System.in

    Lets look at some of the changes and new features in the Java Virtual Machine

    Metadata allows programmer to specify annotations for parts of a program. An annotation is a modifier consisting of an annotation type and zero or more element-value pairs, each of which associates a value with a different element of the annotation type. The purpose of an annotation is simply to associate information with the annotated program element. Annotations can be used by tools such as compilers, IDEs and runtime tools to produce derived files, whether that is something like a new source file, a deployment descriptor or some other file. Java already has some annotations, but these are not organised in a formal way, which is what metadata does. For example, the Serializeable interface contains no methods. If you create a class that implements Serializeable, what does it do? The answer is that implementing the interface is used as a marker (or annotation) to tell the compiler that this class can be serialised. The compiler will then add apropriate code to perform serialisation when required. Xdoclets is another example of a form of annotation that can be used to derive deployment descriptors, etc from infromation contained in the source file. Annotations may be used as modifiers in any declaration, whether package, class, interface, field, method, parameter, constructor, or local variable. Annotations may also be used on enum constants. Such annotations are placed immediately before the enum constant they annotate.

    Lets look at some of the changes and new features in the Java Virtual Machine

    New I/O APIs The new I/O (NIO) APIs introduced in version 1.4 provide new features and improved performance in the areas of buffer management, scalable network and file I/O, character-set support, and regular-expression matching. These new APIs are supported in both client and server compilers. With NIO, developers can now write ultra-scalable, high-performance server applications such as Web, application, file, and database servers. They can also write compute-intensive scientific, technical, and graphics applications that require fast access to large quantities of data. I/O operations that previously required programming in C or C++ can now be performed using the Java language, but with the performance of a native C or C++ application. · The new network I/O package dramatically increases the number of simultaneous connections that a server can handle by removing the need to dedicate one thread to every open connection. · New file I/O supports read, write, copy, and transfer operations that are up to twice as fast as the current file I/O facilities. It also supports file locking, memory-mapped files, and multiple concurrent read/write operations.

    Unfortunately, there aren't many benchmarks that span back to the beginning of Java. This one, (named Volano) probably isn't the best as a general purpose benchmark either. But the improvement is dramatic: 7 times better performance since 1.2.2. But this doesn't tell the whole story: The Java platform has gotten better, and this benchmark doesn't take advantage of that!

    Unfortunately, there aren't many benchmarks that span back to the beginning of Java. This one, (named Volano) probably isn't the best as a general purpose benchmark either. But the improvement is dramatic: 7 times better performance since 1.2.2. But this doesn't tell the whole story: The Java platform has gotten better, and this benchmark doesn't take advantage of that!

    Lets look at some of the changes and new features in the Java Virtual Machine

    Previously Java has supported several very primitive mechanisms for co-ordinating a number of threads. The synchronized keyword can be applied to methods or code blocks and the Thread class supports the wait, notify, sleep and interrupt mothods. The problem with these primitive mechanisms is that they are just that: primitive. As we will see the new utilities will greatly enhance Java applications in terms of scalability, performance, readability and thread safety.

    The idea behind the new concurrency utilities is to provide a much richer set of functions that programmers can use to create simple and powerful multi-threaded applications, in the same way that the Collections classes provided a much richer set of data structure based APIs. By providing much finer granularity of locking and different approaches such as multiple read-single write locks a secondary aim is t o enable the performance of a multi-threaded Java application to match or exceed that of native C applications in the high-end server environment. Previously Java has supported several very primitive mechanisms for co-ordinating a number of threads. The synchronized keyword can be applied to methods or code blocks and the Thread class supports the wait, notify, sleep and interrupt mothods. The problem with these primitive mechanisms is that they are just that: primitive. As we will see the new utilities will greatly enhance Java applications in terms of scalability, performance, readability and thread safety.

    Here is a list of things we'll talk about in this session. This is not an exhaustive list of all the new features, but given the limited time we have this should give you a good grasp of the main areas of functionality. One of the main changes in using the new concurrency utilities is the concept of moving away from interacting directly with a thread object. As we'll see the new and preferred way is through an interface called ExecutorService. There are several factory methods available to easily provide the programmer with standardised mechanisms for the Executor such as thread pools, single thread and priority threads. # Task Scheduling Framework - The Executor framework is a framework for standardizing invocation, scheduling, execution, and control of asynchronous tasks according to a set of execution policies. Implementations are provided that allow tasks to be executed within the submitting thread, in a single background thread (as with events in Swing), in a newly created thread, or in a thread pool, and developers can create of Executor supporting arbitrary execution policies. The built-in implementations offer configurable policies such as queue length limits and saturation policy which can improve the stability of applications by preventing runaway resource consumption. # Concurrent Collections - Several new Collections classes have been added, including the new Queue and BlockingQueue interfaces, and high-performance, concurrent implementations of Map, List, and Queue. Until now it has required relatively complex coding to allow a child thread to return a result to the its parent. This is even more complex when it is necessary to synchonize the threads so that the parent can only continue when the child has completed generatijng the result. This becomes very simple now through the use of Callable and Future. Semaphores are a well understood mechanism that are now supported on Java. BlockingQueues allow simple data structures to be used by multiple threads in a concurrent way such that the programmer is not responsible for ensuring safe concurrent access. Lastly the idea of an Atomic variable that can safely be accessed and modified is also iincluded in the concurrency utilities.

    Here is a list of things we'll talk about in this session. This is not an exhaustive list of all the new features, but given the limited time we have this should give you a good grasp of the main areas of functionality. One of the main changes in using the new concurrency utilities is the concept of moving away from interacting directly with a thread object. As we'll see the new and preferred way is through an interface called ExecutorService. There are several factory methods available to easily provide the programmer with standardised mechanisms for the Executor such as thread pools, single thread and priority threads. # Task Scheduling Framework - The Executor framework is a framework for standardizing invocation, scheduling, execution, and control of asynchronous tasks according to a set of execution policies. Implementations are provided that allow tasks to be executed within the submitting thread, in a single background thread (as with events in Swing), in a newly created thread, or in a thread pool, and developers can create of Executor supporting arbitrary execution policies. The built-in implementations offer configurable policies such as queue length limits and saturation policy which can improve the stability of applications by preventing runaway resource consumption. # Concurrent Collections - Several new Collections classes have been added, including the new Queue and BlockingQueue interfaces, and high-performance, concurrent implementations of Map, List, and Queue. Until now it has required relatively complex coding to allow a child thread to return a result to the its parent. This is even more complex when it is necessary to synchonize the threads so that the parent can only continue when the child has completed generatijng the result. This becomes very simple now through the use of Callable and Future. Semaphores are a well understood mechanism that are now supported on Java. BlockingQueues allow simple data structures to be used by multiple threads in a concurrent way such that the programmer is not responsible for ensuring safe concurrent access. Lastly the idea of an Atomic variable that can safely be accessed and modified is also iincluded in the concurrency utilities.

    As mentioned earlier programmers should now not interact directly with the Thread class. Before, we would create a class that implemented the Runnable interface. To start this in a new thread we would use a line like this: create a new thread with using the Runnable class and call the start method that would in turn call the run method in our class. This is still quite correct, but the idea is to replace this with an abstracted interface, Executor. Instead of calling start we call execute. Since this is abstracted away from the Thread class it becomes a simple task to change the way we handle the threading should we wish to do so at a later date. For example, we could start with a piece of code that creates a single thread to execute our new code. As requirements and processing power change we find that we need to run a number of threads for our class. We can simply change the factory method we use to create a thread pool and we are then able to use the same class in a number of threads rather than just one.

    Here is an example of code that uses the new Executor, Executors and ExecutorService classes. The example is a standard web service class that needs to handle a number of incoming connections simultaneously through a number of separate threads. The number of threads needs to be bounded to prevent the system from running out of resources when the load becomes too high. Previously it would have been necessary to create your own thread pooling class that would create a set of threads and then manage all of the alloaction and deallocation of those threads with all of the required concurrent access controls. With the concurrency utilities this is all provided by default. In the main routine we initialise a new fixed thread pool with a size of 7. We use the newFixedThreadPool method of the Executors class. This will return a ExecutorService object. Since ExecutorService implements the Executor interface we can assign it to an Executor object reference. To handle an incoming connection we simply call execute on our pool object passing it a Runnable object (which in this case is defined through an inner class). The run method does whatever work we need the thread to do. Whenever connections come in they will be allocates a thread from the pool. When the run method completes the thread will automatically be returned to the pool. If a connection comes in and all threads are in use the main loop will block until a thread is freed.

    The Lock interface provides more extensive locking operations than using a synchronized block. Because we are using methods of a class to explicitly perform the lock and unlock operations the programmer needs to be more careful in its use. With a synchronized block of code it is impossible to forget to unlock it. Once the code execution leaves that block whether normally or through some for of exception, the lock is released. Using the Lock class the programmer must typically use a try-finally construct and put the unlock call within the finally clause to ensure that the lock is always released. One advantage of the Lock interface over synchronized is the ability to not block if a lock is not available. The tryLock method will always return immediately, returning true if the lock was aquired or false if not. This method may also be called with a timeout parameter so the thread will only block for the specified time if the lock is not aquired. ReentrantLock provides a concrete implementation of the Lock interface. The thread that holds the lock can call the lock method multiple times without blocking. This is especially useful in recursive code that needs to protect access to a certain section of code.

    ReentrantLock provides a concrete implementation of the Lock interface. The thread that holds the lock can call the lock method multiple times without blocking. This is especially useful in recursive code that needs to protect access to a certain section of code.

    The ReadWriteLock permits multiple threads to have read access to a protected piece of code, but only one thread may access the code in write mode. Effectively the ReadWriteLock consists of two locks that are implemented as inner classes. If a thread aquires the read lock other threads may also aquire the read lock. If a read lock is held no thread may aquire the write lock until all read locks have been released. If a thread holds the write lock, no thread may aquire either the write lock or a read lock. ReadWriteLock is an interface. RentrantReadWriteLock is a concrete implementation of this interface.

    The BlockingQueue interface is a Queue that additionally supports operations that wait for the queue to become non-empty when retrieving an element, and wait for space to become available in the queue when storing an element. A BlockingQueue does not accept null elements. ArrayBlockingQueue is a concrete implementation of the BlockingQueue interface. An ArrayBlockingQueue is a bounded blocking queue backed by an array. This queue orders elements FIFO (first-in-first-out). The head of the queue is that element that has been on the queue the longest time. The tail of the queue is that element that has been on the queue the shortest time. New elements are inserted at the tail of the queue, and the queue retrieval operations obtain elements at the head of the queue. The Blocking queue provides methods to insert and remove objects from the queue (it is generic so can be typed). put() adds the specified element to the tail of this queue, waiting if necessary for space to become available. offer() inserts the specified element at the tail of this queue if possible, returning immediately if this queue is full. peek() retrieves, but does not remove, the head of this queue, returning null if this queue is empty. take() retrieves and removes the head of this queue, waiting if no elements are present on this queue. poll() retrieves and removes the head of this queue, null if this queue is empty. poll can also be specified with a time out so that the call will wait if necessary up to the specified wait time if no elements are present on this queue.

    Here is an example of the use of a BlockingQueue. The class implements a logger that will be used by a number of threads to record information. The constructor takes a BlockingQueue (with type argument String). In the run method messages are retrieved from the queue using the take method. When the queue is empty the logging thread will block until messages become available. Once a message is retrieved it can be logged in whichever way is required.

    Having defined our logging thread here is a class that uses the logger. A new ArrayBlockingQueue is instantiated with a type argument of String and a size of 10 elements. This is passed to the logger constructor as required. We can now start a number of threads that use this logger to record messages. We use the put method on the messageQueue. If the queue is full the thread will block until the logger has removed messages. The BlockingQueue will handle contention in a thread safe way should multiple threads be waiting for space to become available in the queue.

    Lets look at some of the changes and new features in the Java Virtual Machine

    Why are we here? In C/C++ you do the memory management. You make the calls to malloc() and the calls to free(). Forget the calls to free() and you're leaking memory.. And, of course, you don't use the memory once it's been freed. And, you free memory exactly once.

    In a nutshell, a GC ... Our garbage collectors are generational, meaning we divide the heap into two regions and don't have to always collect the entire heap. When we only collect one of the regions we call it a minor collection. Minor collections are typically much faster than major collections and often collect enough memory so as to delay the more expensive major collection.

    Java does the memory management for you. The JVM finds the data that is still in use by the program. This data is referred to a reachable. Anything else is collected as garbage. You never have the equivalent of a dangling pointer. If you have a reference to data, it's there, it has not been collected as garbage. No free's obviously means no double frees. In principle you cannot have a true memory leak but there are things that you can do that are as bad in practice. Basically, you have a reference to data that is never going to be used again. This is more accurately described as unintential object retention but is often just called a memory leak. If your program has such a memory leak, you'll ...

    So garbage collection is your friend. The source of some ugly bugs has removed. You spend more time on the interesting stuff. You don't have to think about memory management as much in your design. But there are some costs. Your going to have pauses in the application execution when a GC occurs. You don't know when a GC is going to occur and don't know how long it is going to take. Finalization depends on GC's. User's of you programs may want to choose among the different collectors to achieve a particular performance (e.g., better throughput or shorter pause times). Some tuning may be required.

    The point here is to make it so that the garbage collection proces is not as disruptive to your application. So the garbage collector works at the same time as your application , short stop do a little work then go back, so that you dont see one long pause. Has some overhead that lowers throughput a little. The young generatons collections are short already so there is no need to put that extra overhead on the young generation We only do incremental of the old generation

    Before going further let me tell you about memory management on a modern Java platform. Allocation is definitely not slow. It was slow in ... Garbage collection has gotten much, much faster than in the early days but a collection does still happen all at the same time so it's noticeable. We don't use reference counting. That's notable because reference counting does slow down the execution of the program. Because early performance was an issue, there's some lingering advice on how to get better performance. Much of that is out dated. And some of the bad advice actually leads to memory leaks.

    Memory allocation is fast , really cheap You don't have to keep track of the remembered set, tracking pointers from old to young, does not have to be done for younger objects. Short lived objects can be reclaimed very fast

    Okay, so we don't have true memory leak, right? But we can hold onto objects that are never going to be used again. You can find plenty of examples of such objects ... In the best case such objects cause more work for the garbage collector. In the worst case you can get an out-of-memory exception because of them. In the next few slides we'll look at three examples of these types of memory leaks.

    In this example an object that stays around longer than it is needed. “ byteArray” is part of “LeakyChecksum” so will live as long as the LeakyChecksum object live. It is. however only. needed during the invocation of geFileChecksum. Now maybe this is ok, but realize that byteArray is going to be as large as the largest file ever read, the garbage collector has to look at it at each collection, and the space would be used more profitably for the allocation of other objects.

    This third example of a memory leak is less easy to workaround. You have an object and you want to associate some information with that object but you cannot put the information in the object itself. In this case you have a socket and want to associate a user id with the socket. A natural solution is to create a map between the socket and the user id as here in the SocketManager. Here the example uses a HashMap w

    Here's the example with a fix using the WeakHasMap. WeakHashMap give you the direct connection between the key and the metadata that you need here. Don't replace all your HashMaps with WeakHashMaps. Reference processing does cost during GC and it would be a waste to always use it.

    Have a explicit reason if you are going to null a reference. Mostly it doesn't help. Occasionally it's exactly the wrong thing to do. A System.gc() will trigger an full collections. In tuning the GC we often try hard to minimize full collections. Understand why you are doing System.gc(). Allocation is fast so just use it. Object pooling has costs in terms of filling up the heap so, again, understand what you are doing.

    You are not guaranteed that a finalizer will ever run so, if you use them, you need design for that contigency. Regarding finalization we mostly hear from people who are trying to manage a scarce native resource which is probably the wrong thing to do. Try to use finally block first. That's the simplest and most deterministic.

    Lets look at some of the changes and new features in the Java Virtual Machine

    The big goal of “smart tuning” sometimes referred to as ergonomics, was good out-of-the-box performance for server applications. From the early days the VM has been tuned to run well with desktop applications because the overwelling majority of executions were for desktop applications. That hurts when customers run benchmarks for large server applications because that is often done without tuning the VM. In tiger we look at the machine we're running on and try to make some smarter choices. We've also added a simplified way of tuning garbage collection.

    This slide shows the effects of tuning on 4 benchmarks. This is without “Smart tuning”. Bigger is better. The 1.4.2 untuned VM is in blue and the hand tuned tiger VM is in red. Tuning can make a big difference. Business logic – specjbb2000 Bytecodes – specjvm98 i/o – jetstream Scientific – scimark2

    This is tiger tuned versus out-of-the-box performance on the same benchmarks. The blue is the out-of-the-box performance for tiger and the red again is the hand tuned tiger VM. Smart tuning has made tiger out-of-the-box performance is much closer to the tuned performance.

    Lets look at some of the changes and new features in the Java Virtual Machine

    Figure above shows the architecture of J2SE 5.0 monitoring and management support. In the 5.0 release, the Java virtual machine (JVM) is highly instrumented for monitoring and management. The platform instrumentation provides information on performance, resource consumption, and the JVM and logging settings of applications running on the Java platform. JMX provides a standard way to instrument the Java runtime environment and applications, and the JMX Remote API allows that instrumentation to be accessed remotely. The instrumentation is accessible through the JMX managed bean (MBean) interfaces, which are registered in the platform MBean server. Applications can also create their own MBeans and register them in the platform MBean server, which can serve as a single point for remote access. A JMX-compliant client, such as JConsole, can connect to the platform MBean server and manage the application (as well as the Java platform) using JMX technology.

    java.lang.management provides the management interface for monitoring and management of the Java virtual machine as well as the operating system on which the Java virtual machine is running. It allows both local and remote monitoring and management of the running Java virtual machine. A platform MXBean is a managed bean that defines the management interface for one component for the platform and is specified in the ManagementFactory class. MXBeans are built into the JVM and can be accessed via, for example: RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean(); The java.lang.management package defines the management interface of the following components: Management Interface Description ClassLoadingMXBean Class loading system of the Java virtual machine. CompilationMXBean Compilation system of the Java virtual machine. MemoryMXBean Memory system of the Java virtual machine. ThreadMXBean Threads system of the Java virtual machine. RuntimeMXBean Runtime system of the Java virtual machine. OperatingSystemMXBean OS on which the Java virtual machine is running. GarbageCollectorMXBean Garbage collector in the Java virtual machine. MemoryManagerMXBean Memory manager in the Java virtual machine. MemoryPoolMXBean Memory pool in the Java virtual machine.

    Lets look at some of the changes and new features in the Java Virtual Machine

    Favorites, Groups & Events

    Java 5 6 Generics, Concurrency, Garbage Collection, Tuning - Presentation Transcript

    1. J2SE 5.0, 6.0 Generics Concurrency, Garbabe Collection
      • Carol McDonald
        • Java Technology Architect
          • Sun Microsystems, Inc.
    2. Speaker’s Qualifications
      • Carol cDonald:
        • Java Architect at Sun Microsystems
        • Before Sun, worked on software development of:
          • Application to manage car Loans for Toyota (>10 million loans)
          • Pharmaceutical Intranet ( Roche Switzerland)
          • Telecom Network Mgmt ( Digital France)
          • X.400 Email Server ( IBM Germany)
    3. Agenda
      • Language Changes
        • Generics & Metadata
      • Library API Changes
        • Concurrency utilities
      • Garbage Collection
      • Virtual Machine
      • Monitoring & Management
      • Next Release: Mustang
    4. J2SE 5.0 Design Themes
      • Focus on quality , stability, compatibility
      • Big emphasis on scalability
        • exploit big heaps, big I/O, big everything
      • Ease of development
        • Faster, cheaper, more reliable
    5. Java Language Changes
      • JDK 1.0
        • Initial language, very popular
      • JDK1.1
        • Inner classes, new event model
      • JDK 1.2, 1.3
        • No changes at language level
      • JDK 1.4
        • Assertions (minor change)
      • JDK 5.0
        • Biggest changes to language since release 1.0
        • 2004
        • 2006
        • J2SE 5
        • “ Tiger”
        • Java SE 6
        • “ Mustang”
        • 2007
        • Java SE 7
        • “ Dolphin”
      Java SE road map
        • 2008
        • 2003
        • 2002
        • 2005
        • J2SE 1.4
        • EOL
        • J2SE 1.3.1
      • 5.0 Java SE 5 2004/9
      • 1. 6 .0 Java SE 6 2006/12
      • 1. 7 .0 Java SE 7 2008
    6. Tiger Is Everywhere Tiger 1.4.x Completed downloads per month
    7. Over 262,295,496 downloads served! Tiger Is Everywhere
    8. Pre-installed on > 60 % of new PCs Tiger Is Everywhere
    9. ≥ 99.999 % availability Previous best: 99.98% for 1.4.2 Tiger Is Stable
    10. Tiger Is Fast Server Benchmark: SPECjbb2000
      • Tiger [Java SE 5] Features Overview
      • JDK 6 Features Overview
    11. Java SE 1.5 Language Changes
    12. Seven Major New Features
      • Generics
      • Autoboxing/Unboxing
      • Enhanced for loop (“foreach”)
      • Type-safe enumerations
      • Varargs
      • Static import
      • Metadata
    13. Generics
    14. Is there a problem in here? Vector v = new Vector(); v.add(new Integer (4)); OtherClass.expurgate(v); ... static void expurgate(Collection c) { for (Iterator it = c.iterator(); it.hasNext();) if ((( String )it.next()).length() == 4) it.remove(); }
    15. The Problem (Pre-J2SE 5.0) Vector v = new Vector(); v.add(new Integer (4)); OtherClass.expurgate(v); ... static void expurgate(Collection c) { for (Iterator it = c.iterator(); it.hasNext();) /* ClassCastException */ if ((( String )it.next()).length() == 4) it.remove(); }
    16. Generics
      • Problem: Collection element types
        • Compiler is unable to verify types
        • Assignment must use the cast operator
        • This can generate runtime errors ( ClassCastException )
      • Solution:
        • Tell the compiler what type the collection is
        • Let the compiler fill in the cast
    17. Using Generic Classes
      • Instantiate a generic class to create type specific object
      • Example
      • Vector <String> x = new Vector <String> ();
      • x.add(new Integer(5)); // Compiler error!
      • Vector <Integer> y = new Vector <Integer> ();
    18. Wildcards
      • Method to print contents of any Collection?
      • Wrong!
      • Passing a Collection of type String will give a compiler error
      void printCollection(Collection <Object> c) { for (Object o : c) System.out.println( o ); }
    19. Wildcards
      • Correct way:
      • ? is the wildcard type
      • Collection <?> means Collection of unknown
      void printCollection( Collection <?> c) { for (Object o : c) System.out.println(o); }
    20. Bounded Wildcards
      • A wildcard can be specified with an upper bound
      public void drawAll (List< ? extends Shape >s) { ... } List<Circle> c = getCircles(); drawAll(c) ; List<Triangle> t = getTriangles(); drawAll(t) ;
    21. Autoboxing & Unboxing
    22. Autoboxing/Unboxing of Primitive Types
      • Problem: (pre-J2SE 5.0) Conversion between primitive types and wrapper types (and vice-versa)
        • must manually convert a primitive type to a wrapper type before adding it to a collection
        • int i = 22;
        • List l = new LinkedList();
        • l.add( new Integer(i) );
    23. Autoboxing/Unboxing of Primitive Types
      • Solution: Let the compiler do it
        • Integer intObj = 22 ; // Autoboxing conversion
        • int i = intObj; // Unboxing conversion
        • ArrayList< Integer > al = new ArrayList<Integer>();
        • al .add( i ); // Autoboxing conversion
    24. Enhanced for Loop
    25. Enhanced for Loop (foreach)
      • Problem: (pre-J2SE 5.0)
        • Iterating over collections is tricky
        • Often, iterator only used to get an element
        • Iterator is error prone (Can occur three times in a for loop)
      • Solution: Let the compiler do it
        • New for loop syntax for (variable : collection)
        • Works for Collections and arrays
    26. Enhanced for Loop Example
      • Old code pre-J2SE 5.0
        • void cancelAll(Collection c) {
        • for ( Iterator i = c.iterator(); i.hasNext() ; ){
          • TimerTask task = (TimerTask) i.next();
          • task.cancel();
          • }
        • }
      • New Code
        • void cancelAll(Collection <TimerTask> c) {
          • for ( TimerTask task : c )
          • task.cancel();
        • }
      Iterating over collections, tricky, error prone
      • New for loop syntax:
      • Let the compiler do it
      • Works for Collections and arrays
    27. Type-safe Enumerations
    28. Type-safe Enumerations
      • Problem: (pre-J2SE 5.0) to define an enumeration:
        • Defined a bunch of integer constants:
        • public static final int SEASON_WINTER = 0;
        • public static final int SEASON_SPRING = 1;
      • Issues of using Integer constants
        • Not type safe (any integer will pass),Brittleness (how do add value in-between?), Printed values uninformative (prints just int values)
      • Solution: New type of class declaration
        • enum type has public, self-typed members for each enum constant
        • enum Season { WINTER, SPRING, SUMMER, FALL }
    29. Enumeration Example: public class Card { public enum Suit { spade, diamond, club, heart }; public enum Rank { ace, two, three, four, five, six, seven, eight, nine, ten, jack, queen, king }; private Card (Rank rank, Suit suit) { this.rank = rank; this.suit = suit; } } List< Card > deck = new ArrayList< Card >(); for ( Suit suit : Suit.values ()) for ( Rank rank : Rank.values ()) deck.add(new Card(rank, suit)); Think how much JDK1.4 code this would require!
    30. Varargs
    31. Before Varargs Example //example method that takes a variable number of parameters int sum( Integer[] numbers ) { for(int i: numbers) // do something } // Code fragment that calls the sum method sum( new Integer[] {12,13,20} ); http://www.javaworld.com/javaworld/jw-04-2004/jw-0426-tiger1.html
      • Problem: (in pre-J2SE 5.0) To have a method that takes a variable number of parameters
        • Can be done with an array, but caller has to create the array first
    32. Varargs Example (Cont) //example method that takes a variable number of parameters int sum ( Integer... numbers ) { for(int i: numbers) // do something } // Code fragment that calls the sum method sum( 12,13,20 ); http://www.javaworld.com/javaworld/jw-04-2004/jw-0426-tiger1.html
      • Solution: Let the compiler do it for you:
        • String format (String fmt, Object... args);
        • Java now supports printf(...)
    33. Varargs examples
      • APIs have been modified so that methods accept variable-length argument lists where appropriate
        • Class.getMethod
        • Method.invoke
        • Constructor.newInstance
        • Proxy.getProxyClass
        • MessageFormat.format
      • New APIs do this too
        • System.out. printf (“%d + %d = %d ”, a, b, a+b);
    34. Static Imports
    35. Static Imports
      • Problem: (pre-J2SE 5.0)
        • Having to fully qualify every static referenced from external classes
      • Solution: New import syntax
        • import static TypeName.Identifier;
        • import static Typename.*;
        • Also works for static methods and enums
        • e.g Math.sin(x) becomes sin(x)
    36. Formatted I/O
    37. Simple Formatted I/O
      • Printf is popular with C/C++ developers
        • Powerful, easy to use
      • Finally adding printf to J2SE 5.0 (using varargs)
        • out.printf(“%-12s is %2d long”, name, l);
        • out.printf(“value = %2.2F”, value);
    38. Annotations
    39. Annotations Metadata (JSR-175)
      • Provide standardised way of adding annotations to Java code
        • public @Remote void foo() {}
      • Annotations are used by tools that work with Java code:
        • Compiler
        • IDE
        • Runtime tools
      • Used to generate interfaces, deployment descriptors...
    40. Annotations Example: JAX-RPC
      • Old Code
      • public interface PingIF implements java.rmi.Remote {
        • public void foo() throws java.rmi.RemoteException;
        • }
        • public class Ping implements PingIF {
        • public void foo() {...}
        • }
      • New Code
        • public class Ping {
        • public @Remote void foo() {}
        • }
    41. Virtual Machine
    42. Some Performance Enhancements in JDK 1.4
      • java.nio package
        • Non blocking I/O : improved performance in buffer management, scalable network and file i/o
      • Reflection
        • Many reflective operations rewritten for higher performance (20x)
    43. Some J2SE 5.0 Performance Features
      • Concurrency libraries
      • Garbage collection improvements
      • “ Smart tuning”
      • Small systems performance optimizations
      • Client features
        • Class data sharing
        • Various JFC/Swing and Java 2D™ APIs improvements
      • X86 Optimizations
    44. Quick Performance Fix
      • Always upgrade to the latest version of the JDK/JRE
        • Sun is always working to improve performance
        • Sun is always working to reduce the number of 'undocumented features'
    45. Tiger is Fast Client Benchmark: SwingMark
    46. Tiger Is Fast Server Benchmark: SPECjbb2000
    47. x64 SPECjbb2005 Performance SPECjbb2005 Sun Fire X4100 (2 chip, 2 core, 2 threads) 32,018 SPECjbb2005 bops, 32,018 SPECjbb2005 bops/JVM, Sun Fire X4100 (2 chip, 2 core, 2 threads) 38,090 SPECjbb2005 bops, 19,045 SPECjbb2005 bops/JVM, submitted for review, IBM eServer p5 510 (2 chips, 2 cores, 4 thread) 36,039 bops, 36,039 bops/JVM, Dell SC1425 (2 chips, 2 cores, 4 thread) 24,208 SPECjbb2005 bops, 24,208 SPECjbb2005 bops/JVM, Dell PE 850 (1 chip, 2 cores, 2 thread) 31,138 SPECjbb2005 bops, 31,138 SPECjbb2005 bops/JVM. SPEC® and the benchmark name SPECjbb™ are trademarks of the Standard Performance Evaluation Corporation. Competitive benchmark results stated above reflect results published on www.spec.org as of May 11, 2005. For the latest SPECjbb2005 benchmark results, visit http://www.spec.org/osg/jbb2005. Sun Fire™ X4100 Server Wins
    48. Java is Fast! Grizzly Web Server Benchmark
    49. Java Concurrency
    50. Motivation for Concurrency Utilities
      • Developing concurrent classes was too hard
      • Java has concurrency primitives:
        • wait() , notify() , sleep() , interrupt() , synchronized
        • These are too primitive, Too low level
        • Easy to use incorrectly
          • Incorrect use can produce poor performance
    51. Concurrency Utilities Goals
      • Provide a good set of concurrency building blocks
        • library for concurrency like Collections for data structures
      • Enhance scalability, performance, readability and thread safety of Java applications
      • Beat C performance in high-end server applications
    52. Puzzle: “Ping Pong”
      • 01 class PingPong {
      • 02 public static synchronized void main (String[] a) {
      • 03 Thread t = new Thread() {
      • 04 public void run() {
      • 05 pong();
      • 06 }
      • 07 };
      • 08
      • 09 t.run();
      • 10 System.out.print(&quot;Ping&quot;);
      • 11 }
      • 12
      • 13 static synchronized void pong() {
      • 14 System.out.print(&quot;Pong&quot;);
      • 15 }
      • 16 }
    53. What Does It Print?
      • (a) PingPong
      • (b) PongPing
      • (c) It varies
    54. What Does It Print?
      • (a) PingPong
      • (b) PongPing
      • (c) It varies
      • Not a multithreaded program!
    55. Example How to start a thread
      • public class HelloRunnable implements Runnable {
      • public void run() {
      • System.out.println(&quot;Hello from a thread!&quot;);
      • }
      • public static void main(String args[]) {
      • (new Thread (new HelloRunnable())) .start();
      • }
      • }
    56. Another Look
      • 01 class PingPong {
      • 02 public static synchronized void main(String[] a) {
      • 03 Thread t = new Thread() {
      • 04 public void run () {
      • 05 pong();
      • 06 }
      • 07 };
      • 08
      • 09 t. run (); // Common typo!
      • 10 System.out.print(&quot;Ping&quot;);
      • 11 }
      • 12
      • 13 static synchronized void pong() {
      • 14 System.out.print(&quot;Pong&quot;);
      • 15 }
      • 16 }
    57. How Do You Fix It?
      • 01 class PingPong {
      • 02 public static synchronized void main(String[] a) {
      • 03 Thread t = new Thread() {
      • 04 public void run() {
      • 05 pong();
      • 06 }
      • 07 };
      • 08
      • 09 t. start ();
      • 10 System.out.print(&quot;Ping&quot;);
      • 11 }
      • 12
      • 13 static synchronized void pong() {
      • 14 System.out.print(&quot;Pong&quot;);
      • 15 }
      • 16 }
    58. The Moral
      • Invoke Thread.start , not Thread.run
        • Common error
        • Can be very difficult to diagnose
    59. Concurrency Utilities: JSR-166
      • Task Scheduling Framework: Executor interface replaces direct use of Thread
      • Callable and Future
      • Synchronisers
        • Semaphore, CyclicBarrier, CountDownLatch
      • Concurrent collections : BlockingQueue
      • Lock
      • Atomic
    60. Concurrency Utilities: JSR-166
      • Task Scheduling Framework: Executor interface replaces direct use of Thread
      • No more direct Thread invocation
        • Use myExecutor.execute(aRunnable);
        • Not new Thread(aRunnable).start();
      public interface Executor { void execute (Runnable command); }
    61. Executor Framework for asynchronous execution public interface Executor { void execute (Runnable command); } public interface ExecutorService extends Executor { .. } public class Executors { //Factory methods static ExecutorService newFixedThreadPool(int poolSize); ... } Executor pool = Executors.newFixedThreadPool(5); pool.execute ( runnable ) ;
    62. Creating Executors
      • Factory methods in the Executors class
      public class Executors { static ExecutorService newSingleThreadedExecutor (); static ExecutorService newFixedThreadPool (int poolSize); static ExecutorService newCachedThreadPool (); static ScheduledExecutorService newScheduledThreadPool (); // Other methods not listed }
    63. Thread Pool Example class WebService { public static void main(String[] args) { Executor pool = Executors.newFixedThreadPool(5); ServerSocket socket = new ServerSocket(999); for (;;) { final Socket connection = socket.accept(); Runnable task = new Runnable() { public void run() { new Handler().process ( connection ); } } pool.execute ( task ) ; } } } class Handler { void process (Socket s); }
    64. ExecutorService for Lifecycle Support
      • ExecutorService supports graceful and immediate shutdown
      public interface ExecutorService extends Executor { void shutdown (); List<Runnable> shutdownNow (); boolean isShutdown (); boolean isTerminated (); boolean awaitTermination (long timeout, TimeUnit unit); // additional methods not listed }
    65. ScheduledExecutorService
      • Deferred and recurring tasks
        • Schedule execution of Callable or Runnable to run once after a fixed delay
          • schedule ()
        • Schedule a Runnable to run periodically at a fixed rate
          • scheduleAtFixedRate ()
        • Schedule a Runnable to run periodically with a fixed delay between executions
          • scheduleWithFixedDelay ()
      • Submission returns a ScheduledFuture
        • Can be used to cancel task
    66. ScheduledExecutorService Example ScheduledExecutorService sched = Executors. newSingleThreadScheduledExecutor (); public void runTwiceAnHour(long howLong) { final Runnable rTask = new Runnable() { public void run() { /* Work to do */ } }; final ScheduledFuture<?> rTaskFuture = sched. scheduleAtFixedRate (rTask, 0, 1800, SECONDS); sched. schedule (new Runnable { public void run { rTaskFuture.cancel(true); } }, howLong, SECONDS); }
    67. Synchronize Critical Section
      • E.g., shared resource is an customer account. Certain methods called by multiple threads.
      • Hold monitor lock for as short a time as possible .
      synchronized double getBalance() { Account acct = verify(name, password); return acct.balance; } Lock held for long time double getBalance() { synchronized (this) { Account acct = verify(name, password); return acct.balance; } } Current object is locked Equivalent to above double getBalance() { Account acct = verify(name, password); synchronized (acct) { return acct.balance}; } Better Only acct object is locked – for shorter time
    68. Locks
      • Java provides basic locking via synchronized
      • Good for many situations, but some issues
        • Single monitor per object
        • Not possible to interrupt thread waiting for lock
        • Not possible to time-out when waiting for a lock
        • Block structured approach
          • Aquiring multiple locks is complex
          • Advanced techniques like hand-over-hand locking are not possible
      • New Lock interface addresses these issues
    69. Lock Interface
      • No automatic unlocking
      Interface Lock { void lock (); void lockInterruptibly () throws IE ; boolean tryLock (); boolean tryLock (long t, TimeUnit u) throws IE ; //returns true if lock is aquired void unlock (); Condition newCondition () throws UnsupportedOperationException; } IE = InterruptedException
    70. RentrantLock
      • Simplest concrete implementation of Lock
      • Same semantics as synchronized, but with more features
      • Generally better performance under contention than synchronized
      • Remember Lock is not automatically released
        • Must use a finally block to release
      • Multiple wait-sets supported
        • Using Condition interface
    71. Lock Example Lock lock = new RentrantLock(); public void accessProtectedResource() throws IllegalMonitorStateException { lock.lock(); try { // Access lock protected resource } finally { // Ensure lock is always released lock.unlock(); } }
    72. ReadWriteLock Interface
      • Has two locks controlling read and write access
        • Multiple threads can aquire the read lock if no threads have a write lock
        • Only one thread can aquire the write lock
        • Methods to access locks
        • rwl.readLock().lock();
        • rwl.writeLock().lock();
        • Better performance for read-mostly data access
    73. ReadWriteLock Example ReentrantReadWriteLock rwl = new ReentrantReadWriteLock (); Lock rLock = rwl.readLock (); Lock wLock = rwl.writeLock (); ArrayList<String> data = new ArrayList<String>(); public String getData(int pos) { r.lock () ; try { return data.get (pos); } finally { r.unlock (); } } public void addData(int pos, String value) { w.lock (); try { data.add (pos, value); } finally { w.unlock (); } }
    74. Synchronizers
      • Co-ordinate access and control
      • Semaphore
        • Manages a fixed sized pool of resources
      • CountDownLatch
        • One or more threads wait for a set of threads to complete an action
      • CyclicBarrier
        • Set of threads wait until they all reach a specified point
      • Exchanger
        • Two threads reach a fixed point and exchange data
    75. BlockingQueue Interface
      • Provides thread safe way for multiple threads to manipulate collection
      Interface BlockingQueue<E> { void put (E o) throws IE; boolean offer (E o) throws IE; boolean offer (E o, long t, TimeUnit u) throws IE; E take () throws IE; E poll () throws IE; E poll (long t, TimeUnit u) throws IE; int drainTo (Collection<? super E> c); int drainTo (Collection<? super E> c, int max); // Other methods not listed }
    76. BlockingQueue Implementations
      • ArrayBlockingQueue
        • Bounded queue, backed by an array, FIFO
      • LinkedBlockingQueue
        • Optionally bounded queue, backed by linked nodes, FIFO
      • PriorityBlockingQueue
        • Unbounded queue
        • Uses comparator or natural ordering to determine the order of the queue
    77. Blocking Queue Example: 1 private BlockingQueue<String> msgQueue ; public Logger ( BlockingQueue<String> mq) { msgQueue = mq; } public void run() { try { while (true) { String message = msgQueue.take (); /* Log message */ } } catch (InterruptedException ie) { } }
    78. Blocking Queue Example: 2 private ArrayBlockingQueue messageQueue = new ArrayBlockingQueue<String>(10); Logger logger = new Logger( messageQueue ); public void run() { String someMessage; try { while (true) { /* Do some processing */ /* Blocks if no space available */ messageQueue.put(someMessage) ; } } catch (InterruptedException ie) { } }
    79. Concurrent Collections
      • ConcurrentMap (interface)
        • Extends Map interface with atomic operations
      • ConcurrentHashMap
        • Fully concurrent retrieval
        • Tunable concurrency for updates
          • Constructor takes number of expected concurrent threads
      • ConcurrentLinkedQueue
        • Unbounded, thread safe queue, FIFO
      • CopyOnWriteArrayList
        • Optimised for frequent iteration, infrequent modifications
    80. Summary
      • New concurrency features are very powerful
      • Lots of great features
      • Take time to learn how to use them correctly
      • Use them!
    81. For More Information
    82. Garbage Collection
    83. Classic Memory Leak in C
      • User does the memory management
      • void service(int n, char** names) {
      • for (int i = 0; i < n; i++) {
        • char* buf = (char*) malloc (strlen(names[i]));
        • strncpy(buf, names[i], strlen(names[i]));
      • }
      • // memory leaked here
      • }
      • User is responsible for calling free()
      • User is vulnerable to dangling pointers and double frees.
    84. Garbage Collection
      • Find and reclaim unreachable objects
        • Anything not transitively reachable from the application roots:
          • (thread stacks, static fields, registers.)
        • Traces the heap starting at the roots
          • Visits every live object
        • Anything not visited is unreachable
          • Therefore garbage
      • Variety of approaches
        • Compacting/non-compacting
        • Algorithms: copying, mark-sweep, mark-compact, etc.
    85. Generational Garbage Collection
      • Keeps young and old objects separately
        • In spaces called generations
      • The weak generational hypothesis
        • Most new objects will die young, Concentrate effort on young generation
      Young Generation Old Generation Object Promotion Object Allocation Track These ( Remembered Set )
            • Need to keep track of old-to-young pointers
          • Eventually, have to also collect the old generation
        • Different GC algorithms for each generation
          • “ Use the right tool for the job”
    86. Garbage Collection
      • Garbage collection: Pros
        • Increased reliability – no memory leaks, no dangling pointers
          • Eliminates entire classes of (Pointer) bugs , no segmentation fault, no double frees
        • Improved developer productivity
        • True memory leaks are not possible
          • Still possible for an object to be reachable but not used by the program
          • Best described as unintentional object retention , Can cause OutOfMemoryError
          • Happens less often than in C, and easier to track down
      • Cons
        • Pauses
        • May require tuning – but auto-tuning is getting better!!!
    87. Incremental Garbage Collection
      • decreases/minimizes GC disruption
      • GC works at the same time as the application
        • Short stop do a little work go back
    88. Garbage Collection
      • Myths about garbage collection abound
        • Myth: Allocation and garbage collection are slow
          • In JDK 1.0 , they were slow (as was everything else)
          • Memory management (allocation + collection) in Java is often significantly faster than in C
            • Cost of new Object() is typically ten machine instructions
            • It's just easier to see the collection cost because it happens all in one place
      • Early performance advice suggested avoiding allocation
        • Bad idea!
        • Alternatives (like object pooling ) are often slower , more error prone , and less memory-efficient
    89. Object Allocation (1/2)
      • Typically, object allocation is very cheap!
        • 10 native instructions in the fast common case
        • C/C++ has faster allocation? No!
      • Reclamation of new objects is very cheap too!
        • Young GCs in generationa l systems
      • So
        • Do not be afraid to allocate small objects for intermediate results
        • Generational GCs love small, short-lived objects
    90. Object Allocation (2/2)
      • We do not advise
        • Needless allocation
          • More frequent allocations will cause more frequent GCs
      • We do advise
        • Using short-lived immutable objects instead of long-lived mutable objects
        • Using clearer, simpler code with more allocations instead of more obscure code with fewer allocations
    91. Large Objects
      • Very large objects are:
        • Expensive to allocate (maybe not through the fast path)
        • Expensive to initialize (zeroing)
        • Can cause performance issues
      • Large objects of different sizes can cause fragmentation
        • For non-compacting or partially-compacting GCs
      • Avoid if you can
        • And, yes, this is not always possible or desirable
    92. Object Pooling (1)
      • Legacy of older VMs with terrible allocation performance
      • Remember
        • Generational GCs love short-lived, immutable objects…
      • Unused objects in pools
        • Are like a bad tax, the GC must process them
        • Safety
          • Reintroduce malloc/free mistakes
        • Scalability
          • Must allocate/de-allocate efficiently
          • synchronized defeats the VM’s fast allocation mechanism
    93. Object Pooling (3/3)
      • Exceptions
        • Objects that are expensive to allocate and/or initialize
        • Objects that represent scarce resources
        • Examples
          • Threads pools
          • Database connection pools
        • Use existing libraries wherever possible
    94. Memory Leaks?
      • But, the GC is supposed to fix memory leaks!
      • The GC will collect all unreachable objects
      • But, it will not collect objects that are still reachable
      • Memory leaks in garbage collected heaps
        • Objects that are reachable but unused
        • Unintentional object retention
    95. Memory Leak Types
      • “Traditional” memory leaks
        • Heap keeps growing , and growing, and growing …
        • OutOfMemoryError
      • “Temporary” memory leaks
        • Heap usage is temporarily very high , then it decreases
        • Bursts of frequent GCs
    96. Memory Leak Sources
      • Objects in the wrong scope
      • Lapsed listeners
      • Exceptions change control flow
      • Instances of inner classes
      • Metadata mismanagement
      • Use of finalizers/reference objects
    97. Objects in the Wrong Scope (1/2)
      • Below, names really local to doIt()
        • It will not be reclaimed while the instance of Foo is live
      • class Foo {
      • private String[] names ;
      • public void doIt (int length) {
      • if (names == null || names.length < length)
      • names = new String[length];
      • populate(names);
      • print(names);
      • }
      • }
    98. Objects in the Wrong Scope (2/2)
      • Remember
        • Generational GCs love short-lived objects
      • class Foo {
      • public void doIt(int length) {
      • String[] names = new String[length];
      • populate(names);
      • print(names);
      • }
      • }
    99. Memory Leak Sources
      • Objects in the wrong scope
      • Lapsed listeners
      • Exceptions change control flow
      • Instances of inner classes
      • Metadata mismanagement
      • Use of finalizers/reference objects
    100. Exceptions Change Control Flow (1/2)
      • Beware
        • Thrown exceptions can change control flow
      • try {
      • ImageReader reader = new ImageReader();
      • cancelButton.addActionListener(reader);
      • reader.readImage(inputFile);
      • cancelButton.removeActionListener(reader);
      • } catch (IOException e) {
      • // if thrown from readImage(), reader will not
      • // be removed from cancelButton's listener set
      • }
    101. Exceptions Change Control Flow (2/2)
      • Always use finally blocks
      • ImageReader reader = new ImageReader();
      • cancelButton.addActionListener(reader);
      • try {
      • reader.readImage(inputFile);
      • } catch (IOException e) {
      • ...
      • } finally {
      • cancelButton.removeActionListener(reader);
      • }
    102. Memory Leak Sources
      • Objects in the wrong scope
      • Lapsed listeners
      • Exceptions change control flow
      • Instances of inner classes
      • Metadata mismanagement
      • Use of finalizers/reference objects
    103. Metadata Mismanagement (1/2)
      • Sometimes, we want to:
        • Keep track of object metadata
        • In a separate map
      • class ImageManager {
      • private Map<Image,File> map =
      • new HashMap<Image,File>();
      • public void add(Image image, File file) { ... }
      • public void remove(Image image) { ... }
      • Public File get(Image image) { ... }
      • }
    104. Metadata Mismanagement (2/2)
      • What happens if we forget to call remove (image)?
        • never be removed from the map
        • Very common source of memory leaks
      • We want:
        • purge the corresponding entry when the key is not reachable…
      • That’s exactly what a WeakHashMap does
        • purge the corresponding entry
      • private Map<Image,File> map =
      • new Weak HashMap<Image,File>();
    105. Some Memory Management Myths
      • Myth: Explicitly nulling references helps GC
        • Rarely helpful
          • Unless you are managing your own memory
        • Can be harmful to correctness or performance
      • Myth: Calling System.gc() helps GC
        • Triggers full collection – less efficient
        • Can be a huge performance loss
      • Myth: Avoid object allocation
        • Allocation in Java is lightning fast
          • Avoidance techniques (e.g., pooling ) are very tricky to get right
    106. Local Variable Nulling
      • Local variable nulling i s n ot necessary
        • The JIT can do liveness analysis
      • void foo() {
      • int[] array = new int[1024];
      • populate(array);
      • print(array); // last use of array in method foo()
      • array = null; // unnecessary!
      • // array is no longer considered live by the GC
      • ...
      • }
    107. Some Memory Management Myths
      • Myth: Finalizers are Java's idea of destructors
        • Finalizers are rarely needed and very hard to use correctly!
          • Should only be used for native resources
          • Adds significant work to GC , has significant performance effect
        • Instead, use finally blocks to release resources
      • Resource r = acquireResource();
      • try {
      • useResource(r); } finally {
      • releaseResource(r);
      • }
          • Note resource acquisition is outside the try block
          • Use for file handles, database connections, etc
    108. Virtual Machine Smart Tuning
    109. How “Smart Tuning” Works
      • Provide good “ out of the box ” performance without hand tuning
      • Determine type of machine JVM is running on configure Hotspot appropriately
      • Server machine
        • Larger heap, parallel garbage collector , and server compiler
      • Client machine
        • Same as 1.4.2 ( small heap , serial garbage collector, and client compiler
    110. “ Smart Tuning”
      • Dynamically adjust Java HotSpot VM software environment at runtime
      • Adaptive Heap Sizing policy
      • Simple tuning options based on application requirements not JVM internals
    111. Effects of Tuning Tuned vs. Non-tuned JVM
    112. Hand Tuned vs. Smart Tuning
    113. Monitoring & Management
    114. Memory Leak Detection Tools
      • Many tools to choose from
      • “ Is there a memory leak”?
        • Monitor VM’s heap usage with jconsole and jstat
      • “ Which objects are filling up the heap?”
        • Get a class histogram with jmap or
        • -XX:+PrintClassHistogram and Ctrl-Break
      • “ Why are these objects still reachable?”
        • Get reachability analysis with jhat
    115. Monitoring, Management, Diagnostics
      • GUI tools: JConsole, jhat, VisualGC (NetBeans), dynamic attach
      • Command line tools: jps, jstat, jstack, jmap, jinfo
      • Diagnostics: CTRL-Break handler, heap dump, better OutOfMemoryError and fatal error handling, JNI crashes
      • Tracing/logging: VM tracing and HotSpot probes, DTrace integration
      http://blogs.sun.com/roller/page/dannycoward/20060310
    116. Monitoring and Management
      • Attach on demand for
        • jconsole : can connect to applications that did not start up with the JMX agent
        • jstack : takes a 'photograph' of all the threads and what they are up to in their own stack frames
        • jmap : takes a detailed 'photograph' of what's going on in memory at any one point in time
        • jhat : forensic expert that will help you interpret the result of jmap
    117. J2SE 5.0 Monitoring & Management
    118. Platform Beans (MXBean's)
      • Provides API access to
        • number of classes loaded,
        • threads running
        • Thread state
        • contention stats
        • stack traces
        • GC statistics
        • memory consumption, low memory detection
        • VM uptime, system properties, input arguments
        • On-demand deadlock detection
    119. Jconsole http://www.netbeans.org/kb/articles/jmx-getstart.html
    120. NetBeans Profiler
      • Low overhead profiling
      • Attach to running applications
      • CPU performance profiling
      • Memory profiling
      • Memory leak debugging
      • Task based profiling
      • Processing collected data offline
      • http://www.netbeans.org/kb/55/profiler-tutorial.html
    121. NetBeans Profiler
    122. JDK 6 (Mustang) Features Overview
    123. JDK 6 Component JSRs 202: Class File Update 199: Compiler API 269: Annotation Processors 260: Javadoc ™ Tag Update Ease of Development 221: JDBC ™ 4.0 223: Scripting 105: XML Digital Signature 173: Streaming API for XML XML 222: JAXB 2.0 250: Common Annotations 181: WS Metadata Web Services 224: JAX-WS 2.0 See JSR 270 at http://jcp.org
    124. The JDK 6 Top 10
      • Scripting
      • Web Services
      • Database (JDBC 4.0, Java DB)
      • More Desktop APIs
      • Monitoring and Management
      • Compiler Access
      • Pluggable Annotations
      • Desktop Deployment
      • Security
      • Quality, Compatibility, Stability
    125. Resources and Summary
    126. For More Information (1/2)
      • Memory management white paper
        • http://java.sun.com/j2se/reference/whitepapers/
      • Destructors, Finalizers, and Synchronization
        • http://portal.acm.org/citation.cfm?id=604153
      • Finalization, Threads, and the Java Technology Memory Model
        • http://developers.sun.com/learning/javaoneonline/2005/coreplatform/TS-3281.html
      • Memory-retention due to finalization article
        • http://www.devx.com/Java/Article/30192
    127. For More Information (2/2)
      • FindBugs
        • http://findbugs.sourceforge.net
      • Heap analysis tools
        • Monitoring and Management in 6.0
          • http://java.sun.com/developer/technicalArticles/J2SE/monitoring/
        • Troubleshooting guide
          • http://java.sun.com/javase/6/webnotes/trouble/
        • JConsole
          • http://java.sun.com/developer/technicalArticles/J2SE/jconsole.html
    128. Call for Action!
      • Download and install JDK 5 or JDK 6
      • Start using the new language features ASAP
    129. Resources
      • http://java.sun.com/javase
      • Java.net
      • http://jdk.dev.java.net
    130. Stay in Touch with Java SE
      • http://java.sun.com/javase
      • JDK Software Community
        • planetjdk.org
        • community.java.net/jdk
      • JDK 6
        • http://jdk6.dev.java.net/
        • http://jcp.org/en/jsr/detail?id=270
      • JDK 7
        • http://jdk7.dev.java.net/
        • http://jcp.org/en/jsr/detail?id=277
    131. Thank You!
      • Carol McDonald
        • Java Technology Architect
          • Sun Microsystems, Inc.
    SlideShare Zeitgeist 2009

    + Carol McDonaldCarol McDonald Nominate

    custom

    207 views, 0 favs, 0 embeds more stats

    More info about this document

    © All Rights Reserved

    Go to text version

    • Total Views 207
      • 207 on SlideShare
      • 0 from embeds
    • Comments 0
    • Favorites 0
    • Downloads 17
    Most viewed embeds

    more

    All embeds

    less

    Flagged as inappropriate Flag as inappropriate
    Flag as inappropriate

    Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

    Cancel
    File a copyright complaint
    Having problems? Go to our helpdesk?

    Categories