Java Versions, Features and History
A popular interview question in java is “what is new in Java version X?”. Is that an intelligent question is debatable. I have summarized below important new features added in each major java release till now. I target to highlight important features added in respective release. Apart from below list of features, every release has enhancements and lots of bug fixes.
New features in Java SE 7
Released on July 28, 2011
New features in Java SE 6
Released on December 11, 2006.
New features in J2SE 5.0
Released on September 30, 2004.
New features in J2SE 1.4
Released on February 6, 2002 (first release under JCP).
New features in J2SE 1.3
Released on May 8, 2000.
New features in J2SE 1.2
Released on December 8, 1998.
New features in JDK 1.1
Released on February 19, 1997
JDK Version 1.0
January 23, 1996.
Java (JVM) Memory Types
Java has only two types of memory when it comes to JVM. Heap memory and Non-heap memory. All the other memory jargons you hear are logical part of either of these two.
Heap Memory Class instances and arrays are stored in heap memory. Heap memory is also called as shared memory. As this is the place where multiple threads will share the same data.
Non-heap Memory It comprises of ‘Method Area’ and other memory required for internal processing. So here the major player is ‘Method Area’.
Method Area As given in the last line, method area is part of non-heap memory. It stores per-class structures, code for methods and constructors. Per-class structure means runtime constants and static fields
The above three (heap memory, non-heap memory and method area) are the main jargon when it comes to memory and JVM. There are some other technical jargon you might have heard and I will summarize them below.
Memory Pool Memory pools are created by JVM memory managers during runtime. Memory pool may belong to either heap or non-heap memory.
Runtime Constant Pool A run time constant pool is a per-class or per-interface run time representation of the constant_pool table in a class file. Each runtime constant pool is allocated from the Java virtual machine’s method area.
Java Stacks or Frames Java stacks are created private to a thread. Every thread will have a program counter (PC) and a java stack. PC will use the java stack to store the intermediate values, dynamic linking, return values for methods and dispatch exceptions. This is used in the place of registers.
Memory Generations HotSpot VM’s garbage collector uses generational garbage collection. It separates the JVM’s memory into and they are called young generation and old generation.
Young Generation Young generation memory consists of two parts, Eden space and survivor space. Shortlived objects will be available in Eden space. Every object starts its life from Eden space. When GC happens, if an object is still alive and it will be moved to survivor space and other dereferenced objects will be removed.
Old Generation – Tenured and PermGen Old generation memory has two parts, tenured generation and permanent generation (PermGen). PermGen is a popular term. We used to error like PermGen space not sufficient.
GC moves live objects from survivor space to tenured generation. The permanent generation contains meta data of the virtual machine, class and method objects.
Discussion: Java specification doesn’t give hard and fast rules about the design of JVM with respect to memory. So it is completely left to the JVM implementers. The types of memory and which kind of variable / objects and where they will be stored is specific to the JVM implementation.
Key Takeaways
Java 7 Updates
It has been quite sometime that Java 7 got released with plenty of new features and enhancements that shall interest Java developer community. Following sections of this page cover some of these changes with examples.
Strings in switch statements
In the JDK 7 release, you can use a String object in the expression of a switch statement:
public String getTypeOfDayWithSwitchStatement(String dayOfWeekArg) {
String typeOfDay;
switch (dayOfWeekArg) {
case "Monday":
typeOfDay = "Start of work week";
break;
case "Tuesday":
case "Wednesday":
case "Thursday":
typeOfDay = "Midweek";
break;
case "Friday":
typeOfDay = "End of work week";
break;
case "Saturday":
case "Sunday":
typeOfDay = "Weekend";
break;
default:
throw new IllegalArgumentException("Invalid day of the week: " + dayOfWeekArg);
}
return typeOfDay;
}
The diamond operator "<>"
You can replace the type arguments required to invoke the constructor of a generic class with an empty set of type parameters (<>) as long as the compiler can infer the type arguments from the context. This pair of angle brackets is informally called the diamond.
For example, consider the following variable declaration:
Map<String, List<String>> myMap = new HashMap<String, List<String>>();
In Java SE 7, you can substitute the parameterized type of the constructor with an empty set of type parameters (<>):
Map<String, List<String>> myMap = new HashMap<>();
Java SE 7 supports limited type inference for generic instance creation; you can only use type inference if the parametrized type of the constructor is obvious from the context. For example, the following example does not compile:
List<String> list = new ArrayList<>();
list.add("A");
list.addAll(new ArrayList<>()); // Statement should fail since addAll expects Collection<? extends String>
In comparison, the following example compiles:
List<? extends String> list2 = new ArrayList<>();
list.addAll(list2);
Note: The diamond often works in method calls; however, it is suggested that you use the diamond primarily for variable declarations.
Handling more than one type of exception
In Java SE 7 and later, a single catch block can handle more than one type of exception. Consider the following example, which contains duplicate code in each of the catch blocks:
//Prior to Java 7
catch (IOException ex) {
logger.log(ex);
throw ex;
catch (SQLException ex) {
logger.log(ex);
throw ex;
}
In releases prior to Java SE 7, it is difficult to create a common method to eliminate the duplicated code because the variable ex has different types.
The following example, which is valid in Java SE 7 and later, eliminates the duplicated code:
catch (IOException|SQLException ex) { // java 7 handling more than one type of exception
logger.log(ex);
throw ex;
}
The catch clause specifies the types of exceptions that the block can handle, and each exception type is separated with a vertical bar (|). Some other advantages apart from syntactical improvement:
Note: If a catch block handles more than one exception type, then the catch parameter is implicitly final. In this example, the catch parameter ex is final and therefore you cannot assign any values to it within the catch block.
Re-throwing exceptions with more inclusive type checking
The Java SE 7 compiler performs more precise analysis of rethrown exceptions than earlier releases of Java SE. This enables you to specify more specific exception types in the throws clause of a method declaration.
Consider the following example:
static class FirstException extends Exception { }
static class SecondException extends Exception { }
public void rethrowException(String exceptionName) throws Exception {
try {
if (exceptionName.equals("First")) {
throw new FirstException();
}
else
{ throw new SecondException();
}
}
catch (Exception e) {
throw e;
}
}
This examples's try block could throw either FirstException or SecondException. Suppose you want to specify these exception types in the throws clause of the rethrowException method declaration. In releases prior to Java SE 7, you cannot do so. Because the exception parameter of the catch clause, e, is type Exception, and the catch block rethrows the exception parameter e, you can only specify the exception type Exception in the throws clause of the rethrowException method declaration.
However, in Java SE 7, you can specify the exception types FirstException and SecondException in the throws clause in the rethrowException method declaration. The Java SE 7 compiler can determine that the exception thrown by the statement throw e must have come from the try block, and the only exceptions thrown by the try block can be FirstException and SecondException. Even though the exception parameter of the catch clause, e, is type Exception, the compiler can determine that it is an instance of either FirstException or SecondException:
public void rethrowException(String exceptionName) throws FirstException, SecondException {
try {
// ...
}
catch (Exception e) {
throw e;
}
}
This analysis is disabled if the catch parameter is assigned to another value in the catch block. However, if the catch parameter is assigned to another value, you must specify the exception type Exception in the throws clause of the method declaration.
In detail, in Java SE 7 and later, when you declare one or more exception types in a catch clause, and rethrow the exception handled by this catch block, the compiler verifies that the type of the rethrown exception meets the following conditions:
In releases prior to Java SE 7, you cannot throw an exception that is a supertype of one of the catch clause's exception parameters. A compiler from a release prior to Java SE 7 generates the error, "unreported exception Exception; must be caught or declared to be thrown" at the statement throw e. The compiler checks if the type of the exception thrown is assignable to any of the types declared in the throws clause of the rethrowException method declaration. However, the type of the catch parameter e is Exception, which is a supertype, not a subtype, of FirstException andSecondException.
The try-with-resources statement
The try-with-resources statement is a try statement that declares one or more resources. A resource is as an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.
The following example reads the first line from a file. It uses an instance of BufferedReader to read data from the file. BufferedReader is a resource that must be closed after the program is finished with it:
// Java 7 Code
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}//no finally block required as resources will be closed automatically
}
In this example, the resource declared in the try-with-resources statement is a BufferedReader. The declaration statement appears within parentheses immediately after the try keyword. The class BufferedReader, in Java SE 7 and later, implements the interface java.lang.AutoCloseable. Because the BufferedReader instance is declared in a try-with-resource statement, it will be closed regardless of whether the try statement completes normally or abruptly (as a result of the method BufferedReader.readLine throwing an IOException).
Prior to Java SE 7, you can use a finally block to ensure that a resource is closed regardless of whether the whether the try statement completes normally or abruptly. The following example uses a finally block instead of a try-with-resources statement:
//Before Java 7
static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
}
finally {
if (br != null) br.close();
}
}
You may declare one or more resources in a try-with-resources statement.
Note: A try-with-resources statement can still have catch and finally blocks just like an ordinary try statement. In a try-with-resources statement, any catch or finally block is run after the resources declared have been closed.
Numeric literals with underscores
In Java SE 7 and later, any number of underscore characters (_) can appear anywhere between digits in a numerical literal. This feature enables you, for example, to separate groups of digits in numeric literals, which can improve the readability of your code.
You can place underscores only between digits; you cannot place underscores in the following places:
float pi1 = 3_.1415F; // Invalid; cannot put underscores adjacent to a decimal point
float pi2 = 3._1415F; // Invalid; cannot put underscores adjacent to a decimal point
long ssn= 999_99_9999_L; // Invalid; cannot put underscores prior to an L suffix
int x1 = _52; // This is an identifier, not a numeric literal
int x2 = 5_2; // OK (decimal literal)
int x3 = 52_; // Invalid; cannot put underscores at the end of a literal
int x4 = 5_______2; // OK (decimal literal)
int x5 = 0_x52; // Invalid; cannot put underscores in the 0x radix prefix
int x6 = 0x_52; // Invalid; cannot put underscores at the beginning of a number
int x7 = 0x5_2; // OK (hexadecimal literal)
int x8 = 0x52_; // Invalid; cannot put underscores at the end of a number
int x9 = 0_52; // OK (octal literal)
int x10 = 05_2; // OK (octal literal)
int x11 = 052_; // Invalid; cannot put underscores at the end of a number
Binary literals
In Java SE 7, the integral types (byte, short, int, and long) can also be expressed using the binary number system. To specify a binary literal, add the prefix 0b or 0B to the number. The following examples show binary literals:
// An 8-bit 'byte' value:
byte aByte = (byte)0b00100001;
// A 16-bit 'short' value:
short aShort = (short)0b1010000101000101;
// Some 32-bit 'int' values:
int anInt1 = 0b10100001010001011010000101000101;
int anInt2 = 0b101;
int anInt3 = 0B101; // The B can be upper or lower case.
// A 64-bit 'long' value. Note the "L" suffix:
long aLong = 0b1010000101000101101000010100010110100001010001011010000101000101L;
Fork and Join
The effective use of parallel cores in a Java program has always been a challenge. There were few home-grown frameworks that would distribute the work across multiple cores and then join them to return the result set. Java 7 has incorporated this feature as a Fork and Join framework.
Basically the Fork-Join breaks the task at hand into mini-tasks until the mini-task is simple enough that it can be solved without further breakups. It's like a divide-and-conquer algorithm. One important concept to note in this framework is that ideally no worker thread is idle. They implement a work-stealing algorithm in that idle workers "steal" the work from those workers who are busy.
The core classes supporting the Fork-Join mechanism are ForkJoinPool and ForkJoinTask. The ForkJoinPool is basically a specialized implementation of ExecutorService implementing the work-stealing algorithm.
Supporting dynamism
Java is a statically typed language — the type checking of the variables, methods and return values is performed at compile time. The JVM executes this strongly-typed bytecode at runtime without having to worry about finding the type information.
There's another breed of typed languages — the dynamically typed languages. Ruby, Python and Clojure are in this category. The type information is unresolved until runtime in these languages. This is not possible in Java as it would not have any necessary type information.
There is an increasing pressure on Java folks improvise running the dynamic languages efficiently. Although it is possible to run these languages on a JVM (using Reflection), it's not without constraints and restrictions.
In Java 7, a new feature called invokedynamic was introduced. This makes VM changes to incorporate non-Java language requirements. A new package, java.lang.invoke, consisting of classes such as MethodHandle, CallSite and others, has been created to extend the support of dynamic languages.
Java Weak Reference
Releasing unused objects for garbage collection can be done efficiently using java weak reference. Yes. weak reference is related to garbage collection. In java we need not do anything explicitly for garbage collection (GC), this memory management overhead is taken care by java run-time itself.
Then what is the use of java weak reference? Let us see an example scenario, which will help us understand the problem in detail. Before that, we should be aware there are four types of references in java and they are strong reference, weak reference, soft reference and phantom reference.
Weak Reference
When there are one or more reference to an object it will not be garbage collected in Java. But this rule depends on what type of reference it is. If an object has only weak reference associated with other objects, then it is a valid candidate for garbage collection.
Let us take a sample scenario to understand it better. Let TextView be an object and we will have program generated ids used for its identification. These ids are used in some other object for referencing the TextViews.
...
Map textViewIdMap = new HashMap();
textViewIdMap.put(textView1, iD1);
textViewIdMap.put(textView2, iD2)
...
Key is TextView object and value is the Id. Now, during the execution of the program we have removed a TextView object say textView1. We do not require that view object so we have made it null. Now, what will happen to the key-value pair(textView1, iD1) stored in HashMap. This pair as of now makes no sense and it is not required as that textview itself is null.
So, programmatic we need to ensure that, when a textView is removed then its corresponding entry in the map should be removed. Only then, that object becomes a candidate for garbage collection. Otherwise, even though it is not used at run-time, this stale object will not be garbage collected.
WeakHashMap
There is a predefined Map which uses weak reference. This is an implementation of Map interface and exactly same as HashMap but with only difference of weakrefernce. Key-value pairs extext WeakReference class.
...
private static class Entry<K,V> extends WeakReference<Object> implements Map.
Entry<K,V>...
In WeakHashMap there is a private method name expungeStaleEntires(), which is used to remove stale entries as given in above scenario. This method is internally used before get/getEntry/put/resize/size /…. all methods. Only after expunge done the regular operation is done. It just makes a stale entry ‘null’ and releases it for garbage collection. You may read its source code for more detail.
Strong Reference vs Weak Reference
Strong reference is not something new, it is nothing but what we use in our daily programming. The default reference for objects. Strong reference is strongest of all references, if there there is a strong reference garbage collecter will not even come to this object.
StringBuilder iD1 = new StringBuilder();
A popular interview question in java is “what is new in Java version X?”. Is that an intelligent question is debatable. I have summarized below important new features added in each major java release till now. I target to highlight important features added in respective release. Apart from below list of features, every release has enhancements and lots of bug fixes.
New features in Java SE 7
Released on July 28, 2011
- Strings in switch Statement
- Type Inference for Generic Instance Creation
- Multiple Exception Handling
- Support for Dynamic Languages
- Try with Resources
- Java nio Package
- Binary Literals, underscore in literals
- Diamond Syntax
- Automatic null Handling
New features in Java SE 6
Released on December 11, 2006.
- Scripting Language Support
- JDBC 4.0 API
- Java Compiler API
- Pluggable Annotations
- Native PKI, Java GSS, Kerberos and LDAP support.
- Integrated Web Services.
- Lot more enhancements.
New features in J2SE 5.0
Released on September 30, 2004.
- Generics
- Enhanced for Loop
- Autoboxing/Unboxing
- Typesafe Enums
- Varargs
- Static Import
- Metadata (Annotations)
- Instrumentation
New features in J2SE 1.4
Released on February 6, 2002 (first release under JCP).
- XML Processing
- Java Print Service
- Logging API
- Java Web Start
- JDBC 3.0 API
- Assertions
- Preferences API
- Chained Exception
- IPv6 Support
- Regular Expressions
- Image I/O API
New features in J2SE 1.3
Released on May 8, 2000.
- Java Sound
- Jar Indexing
- A huge list of enhancements in almost all the java area.
New features in J2SE 1.2
Released on December 8, 1998.
- Collections framework.
- Java String memory map for constants.
- Just In Time (JIT) compiler.
- Jar Signer for signing Java ARchive (JAR) files.
- Policy Tool for granting access to system resources.
- Java Foundation Classes (JFC) which consists of Swing 1.0, Drag and Drop, and Java 2D class libraries.
- Java Plug-in
- Scrollable result sets, BLOB, CLOB, batch update, user-defined types in JDBC.
- Audio support in Applets.
New features in JDK 1.1
Released on February 19, 1997
- JDBC (Java Database Connectivity)
- Inner Classes
- Java Beans
- RMI (Remote Method Invocation)
- Reflection (introspection only)
JDK Version 1.0
January 23, 1996.
Java (JVM) Memory Types
Java has only two types of memory when it comes to JVM. Heap memory and Non-heap memory. All the other memory jargons you hear are logical part of either of these two.
Heap Memory Class instances and arrays are stored in heap memory. Heap memory is also called as shared memory. As this is the place where multiple threads will share the same data.
Non-heap Memory It comprises of ‘Method Area’ and other memory required for internal processing. So here the major player is ‘Method Area’.
Method Area As given in the last line, method area is part of non-heap memory. It stores per-class structures, code for methods and constructors. Per-class structure means runtime constants and static fields
The above three (heap memory, non-heap memory and method area) are the main jargon when it comes to memory and JVM. There are some other technical jargon you might have heard and I will summarize them below.
Memory Pool Memory pools are created by JVM memory managers during runtime. Memory pool may belong to either heap or non-heap memory.
Runtime Constant Pool A run time constant pool is a per-class or per-interface run time representation of the constant_pool table in a class file. Each runtime constant pool is allocated from the Java virtual machine’s method area.
Java Stacks or Frames Java stacks are created private to a thread. Every thread will have a program counter (PC) and a java stack. PC will use the java stack to store the intermediate values, dynamic linking, return values for methods and dispatch exceptions. This is used in the place of registers.
Memory Generations HotSpot VM’s garbage collector uses generational garbage collection. It separates the JVM’s memory into and they are called young generation and old generation.
Young Generation Young generation memory consists of two parts, Eden space and survivor space. Shortlived objects will be available in Eden space. Every object starts its life from Eden space. When GC happens, if an object is still alive and it will be moved to survivor space and other dereferenced objects will be removed.
Old Generation – Tenured and PermGen Old generation memory has two parts, tenured generation and permanent generation (PermGen). PermGen is a popular term. We used to error like PermGen space not sufficient.
GC moves live objects from survivor space to tenured generation. The permanent generation contains meta data of the virtual machine, class and method objects.
Discussion: Java specification doesn’t give hard and fast rules about the design of JVM with respect to memory. So it is completely left to the JVM implementers. The types of memory and which kind of variable / objects and where they will be stored is specific to the JVM implementation.
Key Takeaways
- Local Variables are stored in Frames during runtime.
- Static Variables are stored in Method Area.
- Arrays are stored in heap memory.
Java 7 Updates
It has been quite sometime that Java 7 got released with plenty of new features and enhancements that shall interest Java developer community. Following sections of this page cover some of these changes with examples.
Strings in switch statements
In the JDK 7 release, you can use a String object in the expression of a switch statement:
public String getTypeOfDayWithSwitchStatement(String dayOfWeekArg) {
String typeOfDay;
switch (dayOfWeekArg) {
case "Monday":
typeOfDay = "Start of work week";
break;
case "Tuesday":
case "Wednesday":
case "Thursday":
typeOfDay = "Midweek";
break;
case "Friday":
typeOfDay = "End of work week";
break;
case "Saturday":
case "Sunday":
typeOfDay = "Weekend";
break;
default:
throw new IllegalArgumentException("Invalid day of the week: " + dayOfWeekArg);
}
return typeOfDay;
}
The diamond operator "<>"
You can replace the type arguments required to invoke the constructor of a generic class with an empty set of type parameters (<>) as long as the compiler can infer the type arguments from the context. This pair of angle brackets is informally called the diamond.
For example, consider the following variable declaration:
Map<String, List<String>> myMap = new HashMap<String, List<String>>();
In Java SE 7, you can substitute the parameterized type of the constructor with an empty set of type parameters (<>):
Map<String, List<String>> myMap = new HashMap<>();
Java SE 7 supports limited type inference for generic instance creation; you can only use type inference if the parametrized type of the constructor is obvious from the context. For example, the following example does not compile:
List<String> list = new ArrayList<>();
list.add("A");
list.addAll(new ArrayList<>()); // Statement should fail since addAll expects Collection<? extends String>
In comparison, the following example compiles:
List<? extends String> list2 = new ArrayList<>();
list.addAll(list2);
Note: The diamond often works in method calls; however, it is suggested that you use the diamond primarily for variable declarations.
Handling more than one type of exception
In Java SE 7 and later, a single catch block can handle more than one type of exception. Consider the following example, which contains duplicate code in each of the catch blocks:
//Prior to Java 7
catch (IOException ex) {
logger.log(ex);
throw ex;
catch (SQLException ex) {
logger.log(ex);
throw ex;
}
In releases prior to Java SE 7, it is difficult to create a common method to eliminate the duplicated code because the variable ex has different types.
The following example, which is valid in Java SE 7 and later, eliminates the duplicated code:
catch (IOException|SQLException ex) { // java 7 handling more than one type of exception
logger.log(ex);
throw ex;
}
The catch clause specifies the types of exceptions that the block can handle, and each exception type is separated with a vertical bar (|). Some other advantages apart from syntactical improvement:
- Bytecode generated by compiling a catch block that handles multiple exception types will be smaller (and thus superior) than compiling many catch blocks that handle only one exception type each.
- A catch block that handles multiple exception types creates no duplication in the bytecode generated by the compiler; the bytecode has no replication of exception handlers.
Note: If a catch block handles more than one exception type, then the catch parameter is implicitly final. In this example, the catch parameter ex is final and therefore you cannot assign any values to it within the catch block.
Re-throwing exceptions with more inclusive type checking
The Java SE 7 compiler performs more precise analysis of rethrown exceptions than earlier releases of Java SE. This enables you to specify more specific exception types in the throws clause of a method declaration.
Consider the following example:
static class FirstException extends Exception { }
static class SecondException extends Exception { }
public void rethrowException(String exceptionName) throws Exception {
try {
if (exceptionName.equals("First")) {
throw new FirstException();
}
else
{ throw new SecondException();
}
}
catch (Exception e) {
throw e;
}
}
This examples's try block could throw either FirstException or SecondException. Suppose you want to specify these exception types in the throws clause of the rethrowException method declaration. In releases prior to Java SE 7, you cannot do so. Because the exception parameter of the catch clause, e, is type Exception, and the catch block rethrows the exception parameter e, you can only specify the exception type Exception in the throws clause of the rethrowException method declaration.
However, in Java SE 7, you can specify the exception types FirstException and SecondException in the throws clause in the rethrowException method declaration. The Java SE 7 compiler can determine that the exception thrown by the statement throw e must have come from the try block, and the only exceptions thrown by the try block can be FirstException and SecondException. Even though the exception parameter of the catch clause, e, is type Exception, the compiler can determine that it is an instance of either FirstException or SecondException:
public void rethrowException(String exceptionName) throws FirstException, SecondException {
try {
// ...
}
catch (Exception e) {
throw e;
}
}
This analysis is disabled if the catch parameter is assigned to another value in the catch block. However, if the catch parameter is assigned to another value, you must specify the exception type Exception in the throws clause of the method declaration.
In detail, in Java SE 7 and later, when you declare one or more exception types in a catch clause, and rethrow the exception handled by this catch block, the compiler verifies that the type of the rethrown exception meets the following conditions:
- The try block is able to throw it.
- There are no other preceding catch blocks that can handle it.
- It is a subtype or supertype of one of the catch clause's exception parameters.
In releases prior to Java SE 7, you cannot throw an exception that is a supertype of one of the catch clause's exception parameters. A compiler from a release prior to Java SE 7 generates the error, "unreported exception Exception; must be caught or declared to be thrown" at the statement throw e. The compiler checks if the type of the exception thrown is assignable to any of the types declared in the throws clause of the rethrowException method declaration. However, the type of the catch parameter e is Exception, which is a supertype, not a subtype, of FirstException andSecondException.
The try-with-resources statement
The try-with-resources statement is a try statement that declares one or more resources. A resource is as an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.
The following example reads the first line from a file. It uses an instance of BufferedReader to read data from the file. BufferedReader is a resource that must be closed after the program is finished with it:
// Java 7 Code
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}//no finally block required as resources will be closed automatically
}
In this example, the resource declared in the try-with-resources statement is a BufferedReader. The declaration statement appears within parentheses immediately after the try keyword. The class BufferedReader, in Java SE 7 and later, implements the interface java.lang.AutoCloseable. Because the BufferedReader instance is declared in a try-with-resource statement, it will be closed regardless of whether the try statement completes normally or abruptly (as a result of the method BufferedReader.readLine throwing an IOException).
Prior to Java SE 7, you can use a finally block to ensure that a resource is closed regardless of whether the whether the try statement completes normally or abruptly. The following example uses a finally block instead of a try-with-resources statement:
//Before Java 7
static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
}
finally {
if (br != null) br.close();
}
}
You may declare one or more resources in a try-with-resources statement.
Note: A try-with-resources statement can still have catch and finally blocks just like an ordinary try statement. In a try-with-resources statement, any catch or finally block is run after the resources declared have been closed.
Numeric literals with underscores
In Java SE 7 and later, any number of underscore characters (_) can appear anywhere between digits in a numerical literal. This feature enables you, for example, to separate groups of digits in numeric literals, which can improve the readability of your code.
You can place underscores only between digits; you cannot place underscores in the following places:
- At the beginning or end of a number
- Adjacent to a decimal point in a floating point literal
- Prior to an F or L suffix
- In positions where a string of digits is expected
float pi1 = 3_.1415F; // Invalid; cannot put underscores adjacent to a decimal point
float pi2 = 3._1415F; // Invalid; cannot put underscores adjacent to a decimal point
long ssn= 999_99_9999_L; // Invalid; cannot put underscores prior to an L suffix
int x1 = _52; // This is an identifier, not a numeric literal
int x2 = 5_2; // OK (decimal literal)
int x3 = 52_; // Invalid; cannot put underscores at the end of a literal
int x4 = 5_______2; // OK (decimal literal)
int x5 = 0_x52; // Invalid; cannot put underscores in the 0x radix prefix
int x6 = 0x_52; // Invalid; cannot put underscores at the beginning of a number
int x7 = 0x5_2; // OK (hexadecimal literal)
int x8 = 0x52_; // Invalid; cannot put underscores at the end of a number
int x9 = 0_52; // OK (octal literal)
int x10 = 05_2; // OK (octal literal)
int x11 = 052_; // Invalid; cannot put underscores at the end of a number
Binary literals
In Java SE 7, the integral types (byte, short, int, and long) can also be expressed using the binary number system. To specify a binary literal, add the prefix 0b or 0B to the number. The following examples show binary literals:
// An 8-bit 'byte' value:
byte aByte = (byte)0b00100001;
// A 16-bit 'short' value:
short aShort = (short)0b1010000101000101;
// Some 32-bit 'int' values:
int anInt1 = 0b10100001010001011010000101000101;
int anInt2 = 0b101;
int anInt3 = 0B101; // The B can be upper or lower case.
// A 64-bit 'long' value. Note the "L" suffix:
long aLong = 0b1010000101000101101000010100010110100001010001011010000101000101L;
Fork and Join
The effective use of parallel cores in a Java program has always been a challenge. There were few home-grown frameworks that would distribute the work across multiple cores and then join them to return the result set. Java 7 has incorporated this feature as a Fork and Join framework.
Basically the Fork-Join breaks the task at hand into mini-tasks until the mini-task is simple enough that it can be solved without further breakups. It's like a divide-and-conquer algorithm. One important concept to note in this framework is that ideally no worker thread is idle. They implement a work-stealing algorithm in that idle workers "steal" the work from those workers who are busy.
The core classes supporting the Fork-Join mechanism are ForkJoinPool and ForkJoinTask. The ForkJoinPool is basically a specialized implementation of ExecutorService implementing the work-stealing algorithm.
Supporting dynamism
Java is a statically typed language — the type checking of the variables, methods and return values is performed at compile time. The JVM executes this strongly-typed bytecode at runtime without having to worry about finding the type information.
There's another breed of typed languages — the dynamically typed languages. Ruby, Python and Clojure are in this category. The type information is unresolved until runtime in these languages. This is not possible in Java as it would not have any necessary type information.
There is an increasing pressure on Java folks improvise running the dynamic languages efficiently. Although it is possible to run these languages on a JVM (using Reflection), it's not without constraints and restrictions.
In Java 7, a new feature called invokedynamic was introduced. This makes VM changes to incorporate non-Java language requirements. A new package, java.lang.invoke, consisting of classes such as MethodHandle, CallSite and others, has been created to extend the support of dynamic languages.
Java Weak Reference
Releasing unused objects for garbage collection can be done efficiently using java weak reference. Yes. weak reference is related to garbage collection. In java we need not do anything explicitly for garbage collection (GC), this memory management overhead is taken care by java run-time itself.
Then what is the use of java weak reference? Let us see an example scenario, which will help us understand the problem in detail. Before that, we should be aware there are four types of references in java and they are strong reference, weak reference, soft reference and phantom reference.
Weak Reference
When there are one or more reference to an object it will not be garbage collected in Java. But this rule depends on what type of reference it is. If an object has only weak reference associated with other objects, then it is a valid candidate for garbage collection.
Let us take a sample scenario to understand it better. Let TextView be an object and we will have program generated ids used for its identification. These ids are used in some other object for referencing the TextViews.
...
Map textViewIdMap = new HashMap();
textViewIdMap.put(textView1, iD1);
textViewIdMap.put(textView2, iD2)
...
Key is TextView object and value is the Id. Now, during the execution of the program we have removed a TextView object say textView1. We do not require that view object so we have made it null. Now, what will happen to the key-value pair(textView1, iD1) stored in HashMap. This pair as of now makes no sense and it is not required as that textview itself is null.
So, programmatic we need to ensure that, when a textView is removed then its corresponding entry in the map should be removed. Only then, that object becomes a candidate for garbage collection. Otherwise, even though it is not used at run-time, this stale object will not be garbage collected.
WeakHashMap
There is a predefined Map which uses weak reference. This is an implementation of Map interface and exactly same as HashMap but with only difference of weakrefernce. Key-value pairs extext WeakReference class.
...
private static class Entry<K,V> extends WeakReference<Object> implements Map.
Entry<K,V>...
In WeakHashMap there is a private method name expungeStaleEntires(), which is used to remove stale entries as given in above scenario. This method is internally used before get/getEntry/put/resize/size /…. all methods. Only after expunge done the regular operation is done. It just makes a stale entry ‘null’ and releases it for garbage collection. You may read its source code for more detail.
Strong Reference vs Weak Reference
Strong reference is not something new, it is nothing but what we use in our daily programming. The default reference for objects. Strong reference is strongest of all references, if there there is a strong reference garbage collecter will not even come to this object.
StringBuilder iD1 = new StringBuilder();
WeakReference<TextView> weakTextView1 = new WeakReference<TextView>(textView1);
Types of References in Java There are four types of references in Java,
- Strong Reference
- Soft Reference
- Weak Reference
- Phantom Reference
Soft Reference
Soft Reference is slightly stronger that weak reference. Soft reference allows for garbage collection, but begs the garbage collector to clear it only if there is no other option. That is, it is eligible for garbage collection, but garbage collector can remove it based on the memory crunch it has. If it is left with little memory and it is in a position to reclaim memory, then it will collect the soft references.
Phantom Reference
Phantom reference is different from soft/weak reference. This can never be reached before it is cleared in the program. Calling the get() on it return null always. When a phantom referenced object is garbage collected, it is notified via the ReferenceQueue. We can use this to find when it is garbage collected and no use other than that
Soft Reference is slightly stronger that weak reference. Soft reference allows for garbage collection, but begs the garbage collector to clear it only if there is no other option. That is, it is eligible for garbage collection, but garbage collector can remove it based on the memory crunch it has. If it is left with little memory and it is in a position to reclaim memory, then it will collect the soft references.
Phantom Reference
Phantom reference is different from soft/weak reference. This can never be reached before it is cleared in the program. Calling the get() on it return null always. When a phantom referenced object is garbage collected, it is notified via the ReferenceQueue. We can use this to find when it is garbage collected and no use other than that