Java Random Notes

Until I find time to get more organized, here are a number of miscellaneous notes assembled when I find answers to Java questions and don't want to have to go looking for them again.


Some terminology

Constants in Java...

public class Clazz
{
  private final static String         PATHNAME = "src/test/resources/";    // class constant
  private final        String         FILENAME = "test.dat";               // instance constant
  private              List< String > barNames;                            // instance variable

  private void bar( final String barName )                                 // constant parameter
  {
         int    counter;                                                 // local variable
    final double PI = "3.14";                                             // local constant

    for( final String name : barNames )                                   // local "constant" (within code block)
      ...
  }
}

The Java Virtual Machine

At its core, the Java virtual machine (JVM) consists of the following components:

  • Heap
  • Stack
  • PermGen and method area
  • Just-in-time (JIT) compiler
  • Code cache

The heap is where memory is allocated for every new operator you use during the application code development stage.

Local variables which remain within the scope of a method are stored on the stack. As a method or block in a method goes out of scope, those variables are removed. (Note too that once Java objects no longer have live references to them, they are garbage-collected.)

PermGen space stores class and method-level data as well as static variables that are defined by the application. A method area is in PermGen and stores all method, field and constant pool details of the application.

The JIT and the code cache go hand-in-hand. The JVM at its core interprets and converts the Java byte code into assembly code at run-time. Interpreting is a relatively slow process because the code is converted from byte code to machine code on the fly every time a portion of your application code is executed. This is where the JIT compiler swings into action:

The JIT compiler analyzes the application code at run-time to understand which methods can be categorized as "hot" methods. Hot means code fragments that are accessed more frequently. Conceptually, the JIT compiler has a counter for each method executed in order to understand the frequency of usage. When the counter's value reaches a defined threshold, the method becomes eligible to be compiled by the JIT compiler to assembly which is then stored in the code cache. From then on, whenever the JIT compiler comes across a call to such a pre-compiled and cached method, it will no longer try to reinterpret it, but will use the already compiled assembly code. This gives the application an obvious performance boost.


Links

Got Java?

Because I work on Linux, in the past years I've migrated to using OpenJDK. However, when I need Sun's Java (no, I don't mean Oracle's—I'm still a little in denial about that), I go to http://java.sun.com. There I can get it for any platform, including Apple Macintosh OS X.

Because I write software in Java, I download a JDK "privately" which is to say that I put it locally to my user, on a path like /home/russ/dev/jdk1.7.0_51. On Macintosh OS X, which I think give one little-to-no say in the matter, this apparently ends up being more like /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home. (I don't use Macintosh, but one day I might again so this isn't completely irrelevant.)


Setting up JAVA_HOME...

I do this from .profile. I usually maintain a private JDK locally for use by IntelliJ (or Eclipse back in the day) so that, when I'm developing in Java, there are no surprises.

# set up JAVA_HOME...
if [ -e "$HOME/dev/jdk-alternative" ]; then
  # ...to my private copy if present:
  export JAVA_HOME="$HOME/dev/jdk-alternative/"
else
  # ...or to the one on my Linux Mint/Ubuntu system:
  export JAVA_HOME="/usr/lib/jvm/default-java/"
fi

Script finding and isolating Java version

Here.


Some defintions from Javaland
EAR Enterprise archive. An archive containing the enterprise-level Java bean modules.
JAR Java archive. Collection of .class files compiled from .java files plus resources (like properties files) and libraries (more .jar files).
WAR Web archive. Collection of JSPs (.jsp files), .html files, even graphics and other files necessary to the web application.
NAR NiFi archive. Collection of Apache NiFi standard and/or custom processors.

hs_err_pidXXX.log file

...where XXX is the process id (pid), this is Java's (the JVM's) fatal-error log, created with information and the state obtained at the moment of the fatal error.

The JVM option, -XX:ErrorFile=path may be used to specify where this file is created. Otherwise, it's created a) in the working directory of the process assuming adequate space, filesystem permissions and no other issues, or it's created on /tmp. The JVM always attempts to create this file (and, if it fails, worse stuff than just a crashed Java application is afoot on the system).

It's always safe to remove this file when you find it since, if you see it, it's for a crash that's already happened, it was per-pid, the JVM no longer expects to use it and will just create another (even if the same pid is used) when a fatal error occurs.


Utility methods...

A collection of utility methods isn't OOP (with a capital OOP). These methods should be static since their behaviour is not dependent on any specific instance of attributes.


Use of static...

A static variable in a class becomes a single instance for all instantiations of objects of that type. If changed by one, it's changed for all objects. static final will ensure its inability to be modified.

Declare immutable constants as static final. This guards against inadvertant modification and permits the compiler to perform optimizations in the use of those values.


Identifier case...

Use camel-back, lower-case initial in the names of methods and non-constant variables.


Width of characters...

A char cannot be safely converted to byte.


Flow-control...

Never use exceptions for flow-control.


Use of .class...
	String className = ASConfig.class.getName();

Given <class-type> .class. <method>
.class gets the Class object for the class-type and calls the indicated method. In the sample above, the class name is returned.

See http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.8.2


Accessors and mutators

..are formal names for getters and setters.


Conversions

int to String

	int      x = 99;
	String   X = Integer.toString( x );
	// or
	String   X = "" + x;

JUnit testing

See junit.html.


Integers in Java
Type Size Range
name bytes bits minimum maximum
byte 1 8 -128 +127
short 2 16 -32,768 +32,767
int 4 32 -2,147,483,648 +2,147,483,647
long 8 64 -9,223,372,036,854,775,808 +9,223,372,036,854,775,807

Instance variable instantiation

Consider the following class and subclass which illustrate a bizarre point of instance variable initialization. It might be a long time if ever someone actually suffers from this problem, but it makes a useful observation on initialization. The explanation here is a bit awkward and over-stated, but clear, I think.

	class Abc
	{
	  public Abc( Object o )
	  {
	    assignValue( o );
	  }

	  public void assignValue( Object o )
	  {
	    // do nothing...
	  }
	}

	public class Test extends Abc
	{
	  public Object x = null;

	  public Test( Object o )
	  {
	    super( o );
	  }

	  public void assignValue(Object o)
	  {
	    x = o;

	    System.out.println( "x in assignValue: " + x );
	  }

	  public static void main( String args[] ) throws CloneNotSupportedException
	  {
	    Test t = new Test( "Test" );

	    System.out.println( "t: " + t.x );
	  }
	}

Output:

	x in assignValue: Test
	t: null

The output happens because the initialization:

	public Object x = null;

executes after the constructor. So...

	x = 0;

gets overwritten by

	public Object x = null;

The secret is that the compiler in fact arranges to call the explicitly invoked superclass constructor before the (local) constructor will get executed.

The initializations done as part of the class instance variable declarations are part of and occur before the (local) construction process. In our example, they occur implicitly before the statements in the (subclass) constructor, with the exception of the superclass constructor invocation as noted.

Therefore, execution order is not straightforward as it is in C. Hence, here the null initialization runs after the local class' call of its superclass constructor. The compiler in essence absorbs the

	super( o );

statement and runs it before any other constructor statements as well as even before applying the initializations stated in the instance variable declarations.

See http://forums.sun.com/thread.jspa?forumID=31&threadID=5260093.


I/O

Here's a good site for sample code: http://www.exampledepot.com/egs/java.io/pkg.html

See also sample code in com.etretatlogiciels.samples.fileio.


The finally clause

Use this to close streams, file handles, database connections, etc. StreamUtils.close() is your short-hand friend for the first case.

	Properties      properties = new Properties();
	FileInputStream is         = null;

	try
	{
	  is = new FileInputStream( path );
	  properties.load( is );
	}
	catch( FileNotFoundException e )
	{
	  System.out.println( e.getMessage() );
	}
	catch( IOException e )
	{
	  System.out.println( e.getMessage() );
	}
	finally
	{
	  StreamUtils.close( is );
	}

PipeStream

Research this class for transforming an input stream into an output stream and vice-versa.


Reader versus Stream

In Java I/O, a file or other device may be opened on a stream and somewhere in the layer cake that wraps the device may be a reader. A reader augments a stream in that it deals with characters (UTF-8, etc.) rather than bytes.


Synchronization in Java

This is not an exhaustive treatment of concurrency solutions in Java. It is a simple treatment, from a C programmer's mentality, of the Java keyword, synchronized. Java uses this keyword in two ways.

Synchronized blocks

The synchronized keyword is used to synchronize a block of executable statements by referring to an object. This object becomes like a mutex in procedural programming languages: executing all other blocks with reference to object is serialized:

	Object object = new Object();

	synchronized( object )
	{
	  do something with object;
	}
How it works

On its face, object is not any kind of mutex, condition variable, reader-writer lock, barrier or other synchronization primitive that you would expect to declare in a procedural language to manage your protected data in parallel. But in fact, every Java object contains a lock within itself. This lock is formally referred to as a monitor. When the compiler sees synchronized in this situation, it generates code to use the object's monitor.


Synchronized methods

The synchronized keyword is also used to synchronize goings on in a method. This is also like controlling execution of the method based on a mutex, but the object is implied this rather than explicit.

	synchronized void makeSomeoneHappy()
	{
	  do something to make someone happy with several objects;
	}

All synchronized methods share the same mutex (this, as noted). The above is directly equivalent to:

	void makeSomeoneHappy()
	{
	  synchronized( this )
	  {
	    do something to make someone happy with several objects;
	  }
	}
Watch out!

A private member variable in a class isn't safe unless all methods touching it are explicitly synchronized. A public member variable would practically never be safe. In the following class, x is safe, but y is not even though their manipulating methods are synchronized.

	public class TwoCounters
	{
	  private int x = 0;
	  public int  y = 0;

	  public synchronized getX() { return this.x; }
	  public synchronized incX() { this.x++;      }
	  public synchronized zeroX(){ this.x = 0;    }

	  public synchronized getY() { return this.y; }
	  public synchronized incY() { this.y++;      }
	  public synchronized zeroY(){ this.y = 0;    }
	}

This is because code outside this class can freely access y whereas an attempt to access x would be rebuffed by the compiler:

	TwoCounters counter = new TwoCounters();

	counter.y = 99;        PASSES COMPILER, BUT A BAD IDEA!
	counter.x = 99;        COMPILATION ERROR!

The distinction between the two methods of synchronization just contrasted is that in the second case, no actual, explicit object is needed in writing the code to perform serialization. There is no need to create object. Instead, the implied object, this, is used.

(Yup, this is absolutely the first time in over a decade of writing HTML that I have used the <blink> tag: very annoying, isn't it?)

Deadlocking

Between correctly synchronized methods in diverse classes deadlocks can easily occur, in particular, the ABBA. The following is the scenario.

  1. Thread A enters a synchronized method for class Foo. It holds the monitor for Foo's this. Let's say that thread A blocks momentarily on some I/O operation.
  2. Thread B enters a synchronized method for class Bar. It holds the monitor for Bar's this. Thread B also knows about the same instance of Foo as thread A and attempts to enter one of Foo's synchronized methods. Foo's monitor is contested because thread A already has it.
  3. Thread A wakes up from its I/O operation and, having a reference to the instance of Bar that thread B already has locked, decides to attempt to enter one of Bar's synchronized methods.
  4. Thread A is blocked on a monitor held by thread B and thread B is blocked on a monitor held by thread A.

This sort of nightmare is best prevented by careful design. The temptation by bad engineers in a procedural language might be to test whether a lock is going to be contested before attempting to use it and, indeed, it is sometimes impossible to do otherwise. However, all efforts to design logic to avoid doing this should be made. Moreover, as noted next, it was not possible prior to Java 1.5 to perform a try-lock.


More traditional locking in Java

Starting (only) in Java 1.5, a new interface, Lock, is provided to mimic not only mutexes in use in other, especially procedural languages, but also try-locking mutexes, condition variables and reader-writer locks.

Without giving an implementation here (because that is how one chooses to implement a mutex versus a condition variable versus a reader-writer or other kind of lock), this example shows how it is used:

	Lock l = new ...();

	l.lock();

	try
	{
	  do something with resources controlled by lock l;
	}
	finally
	{
	  l.unlock();
	}

This usage is unsurprising and recognizable to any C programmer. The reason for this to exist (finally) in Java is that it gives greater flexibility (if also imposing the inelegant coding duty of maintaining the lock just as in C). Using synchronized does not give you the finer control to do something else in the case the object is contested: you are blocked on permanently on the object (explicit object or implicit this) until the thread that has it locked yields it. Hence the utility of this new interface.


Managed beans (and JSF)

In Java, a managed bean is a resource running in the Java virtual machine (JVM) used for getting and setting application configuration (pull); for collecting statistics (also a pull operation), e.g.: performance, resource usage, problems; and notifying events (push), e.g.: faults and state changes.

A good article with much better examples on this topic than those below can be found here.

A standard managed bean often implements a business interface containing setters and getters for the attributes and the operations (or methods). There are other sorts of managed beans.

The managed bean is also involved in inversion of control (dependency injection) and the POJO (plain-old Java object).

Managed beans and JavaServer Faces (JSF)

Before server-side Java development became the norm, developers managed all of their classes manually. Contemporarily, Java server "containers" (like Tomcat) have become responsible for running applications and POJOs have come back into popularity because they are so simple (as compared to Enterprise JavaBeans) and useful for performing dependency injection (formerly called "inversion of control" or IoC). The JSF managed bean facility is also an IoC framework that makes management of JavaBeans or POJOs easy for JSF developers.

Control of instantiation

The first item of business for IoC is being able to manage instantiation of Java objects. Originally, this was done in a page using JSP's <jsp:usebean> that instantiated a bean for a specified scope. This is now done using faces-config.xml and any Java class with a no-argument constructor may be registered. Imagine a POJO thus:

	public class TemperatureConverter
	{
	    private double  celsius    = 0.0;
	    private double  fahrenheit = 0.0;
	    private boolean initial    = true;

	    public double  getCelsius()                 { return celsius; }
	    public void    setCelsius( double celsius ) { this.celsius = celsius; }
	    public double  getFahrenheit()              { return fahrenheit; }
	    public boolean getInitial()                 { return initial; }

	    public String reset()
	    {
	  	    initial    = true;
	  	    fahrenheit = 0;
	  	    celsius    = 0;
	  	    return "reset";
	    }

	    public String celsiusToFahrenheit()
	    {
	  	    initial    = false;
	  	    fahrenheit = ( celsius * 9 / 5 ) + 32;
	  	    return "calculated";
	    }
	}

The dead give-away that this is a bean is:

In faces-config.xml, the bean, which is otherwise coded as above (no surprise) and included in the application as a simple Java object (POJO), is registered thus:

	<managed-bean>
	    <managed-bean-name>   temperatureConverter          </managed-bean-name>
	    <managed-bean-class>  mypackage.TemperatureConverter</managed-bean-class>
	    <managed-bean-scope>  session                       </managed-bean-scope>
	    <managed-property>
	        <property-name>   celsius    </property-name>
	        <value>           37.0       </value>
	    </managed-property>
	    <managed-property>
	        <property-name>   fahrenheit </property-name>
	        <value>           98.6       </value>
	    </managed-property>
	</managed-bean>

temperatureConverter is sort of arbitrarily named, but follows a common convention of dropping the first letter of the class to lower-case (since it is used in JSF as an indentifier).

In addition, the implicit "properties" of the bean, celsius and fahrenheit can be the target of initialization in the same faces-config.xml file as shown in the example above where the imaginary Celsius-to-Fahrenheit calculator will start up set at the temperature of a human body.

faces-config.xml is found in the typical web application at WEB-INF. For example, in Eclipse by default this is project-name/WebContent/WEB-INF/faces-config.xml. In the example above, the Java code is located at project-name/src/mypackage/TemperatureConverter.java.

Dependency handling

The ability to handle interdependence between Java objects is another requirement of IoC. JSF doesn't handle cyclical dependencies, but managed beans can refer to each other using expression language.

Life-cycle support

Another requirement of IoC is support of the life-cycle of, say, HTTP requests and other durations. Hence, JSF defines various levels of...

...granularity. No (none) granularity is when the bean has no scope, is created on the fly and whenever needed. The request is the bean having scope (and managed properties and values) only for the duration of an HTTP request. By session, the bean properties and values remain in effect (modified as many times or none) for an arbitrary length of time or operations as conceived by the developer, for example, a shopping cart that dies after a user has ordered or left the web site. Finally, the application-scoped bean exists while the application is up and running, for example a database connection.

Configuration support

The primary task of JSF is to present a web interface to a client that is predictably and automatically synchronized with one or a set of managed objects without extensive, spaghetti-like and difficult coding.


System properties

Much is configurable in Java and:

	String property = System.getProperty( property-name);

...is how a property is got. There are three ways they are set.

First, Sun sets them, like java.io.tmpdir, predefined, in its JRE. Other JREs do too and, from platform to platform, there is sometimes the tiniest bit of non-conformance.

Second, you can set them yourself using the command line:

	# java  -Dhow.i.feel=blue  MyClass

Last, you can set them programmatically:

	String libraries = System.getProperty( "java.library.path" );

	if( libraries != null && libraries.length() != 0 )
	  libraries += ":" + "/home/russ/dev/libs";
	else
	  libraries = "/home/russ/dev/libs";

	System.setProperty( "java.library.path", libraries );

File.createTempFile()

A temporary file is created in java.io.tmpdir:

	File f = File.createTempFile( "fun", ".poo" );

	System.out.println( "Just created file "
	                    + f.getName()
	                    + " in directory "
	                    + System.getProperty( "java.io.tmpdir" )
	                   );


The ternary operator

The ternary operator in Java is problematic, having trouble with mixed, ambiguous or unclear typing in places where humans do not.

In the example, a compile-time error is generated. In order to force understanding on the compiler, use parentheses as shown in the subsequent line. This forces evaluation of the expression before settling on what type is its result.

Type mismatch: cannot convert from String to boolean.
	Double x = 9.0;

	System.out.println( "This is a " + ( x == 9.9 ) ? "test" : "cat" + " of the Emergency Broadcast System" );

	/* fixed: */
	System.out.println( "This is a " + ( ( x == 9.9 ) ? "test" : "cat" ) + " of the Emergency Broadcast System" );

Viewing the contents of a JAR

(A quicker way to do this is to follow How to examine a JAR (or WAR) in Linux or to do this from the command line:

$ file-roller jar-name 

)

Dump the particulars including class list for a JAR. If binary jar isn't on $PATH, find it in the JDK under the bin subdirectory. The options are mostly identical to tar:

	russ@taliesin:~/dev/downloads/myfaces-core-1.2.8/lib> jar tvf myfaces-impl-1.2.8.jar
	META-INF/
	META-INF/MANIFEST.MF
	META-INF/services/
	javax/
	javax/faces/
	org/
	org/apache/
	org/apache/myfaces/
	org/apache/myfaces/event/
	org/apache/myfaces/taglib/
	org/apache/myfaces/taglib/core/
	org/apache/myfaces/taglib/html/
	org/apache/myfaces/convert/
	org/apache/myfaces/portlet/
	.
	.
	.
	META-INF/NOTICE.txt
	META-INF/standard-faces-config.xml
	META-INF/myfaces_core.tld
	META-INF/myfaces_html.tld
	META-INF/LICENSE.txt
	META-INF/myfaces-metadata.xml
	javax/faces/Messages_pl.properties
	javax/faces/Messages_ru.properties
	javax/faces/Messages_ja.properties
	javax/faces/Messages_mt.properties
	javax/faces/Messages_it.properties
	javax/faces/Messages_ca.properties
	javax/faces/Messages.properties
	javax/faces/Messages_en.properties
	.
	.
	.
	org/apache/myfaces/taglib/core/ValidateDoubleRangeTag.class
	org/apache/myfaces/taglib/core/SetPropertyActionListenerTag.class
	org/apache/myfaces/taglib/core/LoadBundleTag.class
	org/apache/myfaces/taglib/core/ConvertNumberTag.class
	org/apache/myfaces/taglib/core/PhaseListenerTag$BindingPhaseListener.class
	org/apache/myfaces/taglib/core/ValidatorImplTag.class
	org/apache/myfaces/taglib/core/SubviewTag.class
	org/apache/myfaces/taglib/core/GenericListenerTag.class
	org/apache/myfaces/taglib/core/ConverterImplTag.class
	org/apache/myfaces/taglib/core/LoadBundleTag$BundleMap.class
	org/apache/myfaces/taglib/core/SelectItemTag.class
	org/apache/myfaces/taglib/core/ActionListenerTag.class
	org/apache/myfaces/taglib/core/GenericMinMaxValidatorTag.class
	org/apache/myfaces/taglib/core/DelegateConverter.class
	org/apache/myfaces/taglib/core/ConvertDateTimeTag.class
	org/apache/myfaces/taglib/core/SelectItemsTag.class
	org/apache/myfaces/taglib/core/VerbatimTag.class
	.
	.
	.
	org/apache/myfaces/webapp/StartupServletContextListener.class
	.
	.
	.
	org/apache/myfaces/application/jsp/ViewResponseWrapper$WrappedServletOutputStream.class
	org/apache/myfaces/application/MyfacesStateManager.class
	org/apache/myfaces/application/TreeStructureManager$TreeStructComponent.class
	org/apache/myfaces/application/ApplicationFactoryImpl.class
	org/apache/myfaces/application/DefaultViewHandlerSupport.class
	org/apache/myfaces/application/ActionListenerImpl.class
	META-INF/maven/
	META-INF/maven/org.apache.myfaces.core/
	META-INF/maven/org.apache.myfaces.core/myfaces-impl/
	META-INF/maven/org.apache.myfaces.core/myfaces-impl/pom.xml
	META-INF/maven/org.apache.myfaces.core/myfaces-impl/pom.properties

Runnable (stand-alone) JUnit testing

To run from the command line a JUnit test you've created, you need a main() method to call it. Create your JUnit test class as normal, here, FunTest, create another class with a public static void main( String[] args ) inside that calls it thus:

    import junit.textui.TestRunner;

    public class RunnableFunTest
    {
        public static void main( String[] args )
        {
            TestRunner.run( FunTest.class );
        }
    }

Obviously, when you run this from the command line, you'll also have to make allowances for the JUnit JAR (library) to be present.


Enabling Java assertions...

Java assertions have nothing to do with JUnit. In order to enable them, add -ea (or, -enableassertions) to the Java command line, to the launch configuration in Eclipse or as a default VM argument in the installed JRE (Preferences -> Java -> Installed JREs (select a JDK/JRE) Edit.


Encapsulation is...

...these three things, most importantly:

  1. Separation of concerns, a phrase borrowed from Edger Djikstra, 1975.

    "Let me try to explain to you, what to my taste is characteristic for all intelligent thinking. It is, that one is willing to study in depth an aspect of one's subject matter in isolation for the sake of its own consistency, all the time knowing that one is occupying oneself only with one of the aspects. We know that a program must be correct and we can study it from that viewpoint only; we also know that it should be efficient and we can study its efficiency on another day, so to speak. In another mood we may ask ourselves whether, and if so: why, the program is desirable. But nothing is gained —on the contrary!— by tackling these various aspects simultaneously. It is what I sometimes have called "the separation of concerns", which, even if not perfectly possible, is yet the only available technique for effective ordering of one's thoughts, that I know of."

    An object's information (data) is separate from its interfaces.

  2. Information-hiding, a term borrowed from David Parnas, 1972.

    "We have tried to demonstrate by these examples that it is almost always incorrect to begin the decomposition of a system into modules on the basis of a flowchart. We propose instead that one begins with a list of difficult design decisions or design decisions which are likely to change. Each module is then designed to hide such a decision from the others."

    C.f. Java's private and, to a lesser extent, protected modifiers.

  3. Ripple effects, a term borrow from Wayne Stevens, 1974.

    "The fewer and simpler the connections between modules, the easier it is to understand each module without reference to other modules. Minimizing connections between modules also minimises the paths along which changes and errors can propagate into other parts of the system, thus eliminating disastrous, 'Ripple effects,' where changes in one part causes errors in another, necessitating additional changes elsewhere, giving rise to new errors, etc."

    I.e.: coupling and cohesion.

Problems with supposed encapsulation

Encapsulation is popularly implemented through usage of private attributes with accessors. Using this method to achieve encapsulation when the attribute is a java.util.Collection, java.util.Map, etc. is just plain wrong.

public class MyBean
{
    private Collection collection;

    public Collection getCollection() { return collection; }
    public void setCollection( Collection collection ) { this.collection = collection; }
}

...or even eschewing the setter by using a constructor:

public class MyBean
{
    private Collection collection;

    public MyBean( Collection collection ) { this.collection = collection; }

    public Collection getCollection() { return collection; }
}

...will not make the interior collection immutable since a handle to it on the outside will make it modifiable. The following could be tried:

public class MyBean
{
    private List collection = new ArrayList();

    public MyBean( Collection collection ) { this.collection.addAll( collection ); }

    public Collection getCollection() { return Collections.unmodifiableList( collection ); }
}

Tracking down memory leaks in Java

Here is an article: Monitoring and Detecting Memory Leaks in Your Java Application.

Note that thread-local store use and web applications running in a container like Tomcat can easily sport memory leaks that must be cogitated and analyzed.


Hunting memory leaks in production
  • Observe whether system up-time increases the likelihood of running out of memory.
  • Use jmap to take a memory dump. It doesn't count objects that aren't referred to, which will be the object of garbage collection soon anyway. This means it has a much smaller effect on the production JVM.
  • Think about what your service is doing and how it can be abused by clients. For example, can a client do something that will cause memory to leak, perhaps by making requests that allocate memory or connections repeatedly that are not closed for some reason? This may betray a mistake in your design.
  • Enable the garbage-collection log via JVM argument, -XX:+PrintGC.
  • Use jmap multiple times at calculated intervals to ascertain the memory-accumulating pattern.
    $ jmap -histo:live process-id
    
  • Keep a seconds-based progress log early on in order to understand your service depending on what the service does. Do this using the TRACE level logger. For example, each second, print out
    • number of requests coming into the service
    • number of requests to fire all the way through
    • number of successful requests
    • number of failed requests
    • number of requests timing out
    The objective, of course, is to compare this to the jmap histogram. Anything weird happening is put into better context.

Notes on overt thread safety in Java

I used to code in C and assembly on a multithreaded, multiprocessor operating system (NetWare). I knew all the ins and outs. Java, however, is not C and has different ways of doing things. Here are the details on the Java synchronized keyword:

  • Synchronized code: This locks code down a little like a barrier in C. (Well, okay, not much like that, but it's sort of the same idea.)
    public synchronized method()
    {
      ...
    }
    
  • Synchronize code on a variable: actually, this is what's really happening even in the case above because the variable there is implicit. If execution encounters code attempting to synchronize on the same object, then that object becomes, like a mutext, contended.
  • Another, more intelligent way to support thread-safe execution in Java includes, just as in other languages including C, to eliminate shared data. If threads don't share objects, then it doesn't matter when threads run or what they do to their data.

Replacing Java 6 with Java 7

This is in the context of running Tomcat. See JAVA_HOME for Tomcat.


UnsupportedClassVersionError in Java

When you see a stack trace with...

    java.lang.UnsupportedClassVersionError: SomeClass : Unsupported major.minor version 51.0 (unable to load class SomeClass)
    .
    .
    .

...it probably means that you compiled your application with a Java compiler of a more recent version than the JVM you're trying to run it on.


How to override equals() and hashCode() properly

Equivalence must define a relation that's reflexive, symmetric, transitive and consistent. If null, what's being compared must return false. Apache Commons has some great helps for this.

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;

public class Poop
{
    private String name;
    private int    age;

    public boolean equals( Object o )
    {
        if( o == null )
            return false;
        if( o == this )
            return true;
        if( !( o instanceof Poop ) )
            return false;

        Poop poop = ( Poop ) o;

        return new EqualsBuilder()
                    .append( name, poop.name )
                    .append( age, poop.age )
                    .isEquals();
    }

    public int hashCode()
    {
        return new HashCodeBuilder( 17, 31 )    // two randomly chosen prime numbers
                        .append( name )
                        .append( age )
                        .toHashCode();
    }
}

Visual VM bundled with JDK

Web site: http://visualvm.java.net/.

MBeans

Use to read and set properties with this plug-in directly in memory effectuating changes on the fly.

Launch thus from console:

$ jvisualvm

...and install Tools -> Plugins including:

If, when you click on the MBeans tab, you see:

Data not available because JMX connection to the JMX agent could not be established.

This link sort of applies: http://docs.oracle.com/javase/1.5.0/docs/guide/management/agent.html#remote, but you only need some of it (if you're not debugging remotely).

In Run/Debug configuration, for VM options: -Dcom.sun.management.jmxremote


Dependency injection (Inversion of control)

Better than Guice; Dagger for dependency injection: http://square.github.io/dagger/.


The history of identifier deprecation in Java

I was completely taken by surprise this morning.

These annotations have a rather sordid history including hopeless pleas now in our day exhorting correct usage which, officially and numerously (see stackoverflow.com* et al.) at least, is supposed to consist of employing both annotations simultaneously.

From Oracle (Sun) docs (underlining mine):

NOTE: The Java Language Specification requires compilers to issue warnings when classes, methods, or fields marked with the @Deprecated annotation are used. Compilers are not required by the Java Language Specification to issue warnings when classes, methods, or fields marked with the @deprecated Javadoc tag are accessed, although the Sun compilers currently do so. However, there is no guarantee that the Sun compiler will always issue such warnings.

Using the @Deprecated Annotation

J2SE 5.0 introduces a new language feature called annotations (also called metadata). One of the Java language's built-in annotations is the @Deprecated annotation. To use it, you simply precede the class, method, or member declaration with "@Deprecated."

This next document demonstrates that the Javadoc-looking annotation predates—to at least 1996. Note the statement,

This is the first time the compiler is in any way cognizant of document comment contents. (Once, it made sure that they were at the right place in the parse tree, but this is no longer true.) We did not lightly choose to make the compiler's behavior dependent on the contents of a comment.

(Yeah, no kidding? They must have been desperate. C already long sported #pragmas; I'd have reached the conclusion to implement annotations right then and there, Java 1.1, instead of awaiting Java 1.5.)

http://www.cis.upenn.edu/~bcpierce/courses/629/jdkdocs/guide/misc/deprecated.html

* http://stackoverflow.com/questions/9031832/how-to-declare-or-mark-a-java-method-as-deprecated


OS/system details in Java

http://java.dzone.com/articles/get-your-os-distribution


How I eliminated Oracle/Sun JDK

Not that I feel the need to do this. OpenJDK/JRE usually works fine and so does the Sun JDK/JRE. At work, they were in a "let'd get rid of Oracle" mood and while that's really only a database issue, it was proposed that the baby get tossed out too. No matter. Here's how I did it; I'm running Mint (Ubuntu) these days.

Please note that Oracle/Sun typically installs on the host at /opt/java, e.g.: /opt/java/jdk1.7.0_51. It is not seen via dpkg --list nor removed via apt-get purge/remove.

I'm dumbing this down a bit to reveal all the details that would otherwise have to be guessed at.

If it's really a JDK (and not merely a JRE) and you've done everything right, IntelliJ should start without the "missing tools.jar / please use a proper JDK message".

  1. Install openjdk 7, the one you want.
    ~ $ sudo bash
    ~ # apt-get update
    ~ # apt-get install openjdk-7-jdk
    
  2. Fix up links in /usr/lib/jvm:
    /usr/lib/jvm # ll
    total 56
    drwxr-xr-x   4 root root  4096 Jun 25 12:52 .
    drwxr-xr-x 203 root root 36864 Jun 25 12:52 ..
    lrwxrwxrwx   1 root root    18 Mar 13  2012 java-1.5.0-gcj -> java-1.5.0-gcj-4.6
    drwxr-xr-x   6 root root  4096 Feb  7 14:03 java-1.5.0-gcj-4.6
    lrwxrwxrwx   1 root root    20 Apr 25 12:31 java-1.7.0-openjdk-amd64 -> java-7-openjdk-amd64
    -rw-r--r--   1 root root  2439 Apr 25 12:31 .java-1.7.0-openjdk-amd64.jinfo
    drwxr-xr-x   5 root root  4096 Jun 25 10:56 java-7-openjdk-amd64
    lrwxrwxrwx   1 root root    12 Mar 13  2012 java-gcj -> java-gcj-4.6
    lrwxrwxrwx   1 root root    18 Apr 16  2012 java-gcj-4.6 -> java-1.5.0-gcj-4.6
    -rw-r--r--   1 root root   946 Apr 16  2012 .java-gcj-4.6.jinfo
    
  3. I added this link.
    lrwxrwxrwx   1 root root    26 Jun 25 13:06 java-7 -> ./java-1.7.0-openjdk-amd64
    
  4. Fix up /etc/alternatives.
    /etc/alternatives # ll java
    lrwxrwxrwx 1 root root 30 Feb  7 14:05 java -> /opt/java/jdk1.7.0_51/bin/java
    

    which I changed to:

    /etc/alternatives # ll java*
    lrwxrwxrwx 1 root root 30 Feb  7 14:05 java.old -> /opt/java/jdk1.7.0_51/bin/java
    lrwxrwxrwx 1 root root 28 Jun 25 13:08 java -> /usr/lib/jvm/java-7/bin/java
    

    I can remove java.old once everything is working.

  5. Fix up your .profile, something like:
    export JAVA7_HOME=/usr/lib/jvm/java-7-openjdk-amd647
    export  JAVA_HOME=${JAVA7_HOME}
    export   IDEA_JDK=${JAVA7_HOME}
    export    M2_HOME=/home/russ/dev/apache-maven-3.1.1
    export         M2=${M2_HOME}/bin
    export MAVEN_OPTS="-Xms2048m -Xmx2048m -XX:PermSize=256m -XX:MaxPermSize=512"
    
    PATH=/home/russ/bin:${JAVA_HOME}/bin:${PATH}
    PATH=${PATH}:${M2}
    

    so that your path appears thus:

    ~ $ echo $PATH
    /home/russ/bin:/usr/lib/jvm/java-7/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:\
        /sbin:/bin:/home/russ/dev/apache-maven-3.1.1/bin
    ~ $ which java
    /usr/lib/jvm/java-7/bin/java
    ~ $ java -version
    java version "1.7.0_55"
    OpenJDK Runtime Environment (IcedTea 2.4.7) (7u55-2.4.7-1ubuntu1~0.12.04.2)
    OpenJDK 64-Bit Server VM (build 24.51-b03, mixed mode)
    

The Java @Override snafu

The first things to remember are that Java 5 introduced...

  1. Annotations, including @Override.
  2. Interfaces, which had not existed before (everyone use abstract).

In Java 5, @Override was introduced for use in overriding a method from a superclass (including abstract classes). It was not offered for use on methods implementing a method from an interface.

In Java 7, @Override is tolerated for methods of a class that implement methods listed in an interface. However, it is not necessary. This is why you don't get errors for either method below:

public interface Foo
{
    public void fooit();
    public void barit();
}

public class Bar implements Foo
{
    @Override
    public void fooit() { }

    public void barit() { }
}

Nevertheless, when compiling with Java 6, you do get an error for the implementation of fooit().

I personally think it makes more sense not to use @Override when implementing an interface's contractual methods, but it's only a problem when you maintain code compiled sometimes by JDK 5/6 and sometimes by JDK 7/8.


Swiss Java knife

A useful, open-source tool to add to Java diagnostic toolkit. Swiss Java Knife offers a number of commands:

  • jps - Similar to the jps tool that comes with the JDK.
  • ttop - Similar to the linux top command.
  • hh - Similar to running the jmap tool that comes with the JDK with the -histo option.
  • gc - Reports information about garbage collection in real time.
  • mx - Allows you to do basic operations with MBeans from the command line.
  • mxdump - Dumps all MBeans of the target java process to JSON.

Links:


Java thread safety

How JEE applications execute

  1. Applications start with one master thread, the main thread, which hangs around keeping the application alive. This is usually part of the container in Java EE.
  2. On receiving user input or on receiving a request from client, the master thread may start new thread(s) to get the work done. Some entry method is called on your managed component - like doGet() or doPost() or a bean's business method.
  3. From this point onward you are not creating any further threads, so you are coding with a single thread in mind.
  4. As your code executes, you may create objects with new and work with them.
  5. You may share few of these objects with the container or hold static reference to the objects. These can become accessible to other threads.
  6. Your code can also access container-provided objects, singletons (and other objects held in static references), etc. which may be created by other threads and are visible to you.

How visibly to show code is safe

  1. Write minimal amounts of code in static methods—implement business logic as instance methods not static methods. Even if you write static methods, avoid static instance variables (just do some work, don't store anything).
  2. Don't expose: Keep as many objects unshared as possible. For example, don't write getters and setters for internal variables.
  3. Use lots of new and don't unnecessarily reuse. For example, don't reuse a SimpleDateFormat. Just create one each time you need to format or parse a date (or keep it as a private instance variable and mark it final. But don't make it static. Once you make it static it can be accessed by multiple threads).
  4. Similarly, create new ArrayLists and StringBuilders freely, don't reuse. (Code reuse is good, object reuse is bad)
  5. Create new instances every time for custom objects also. For example, create new BO and DAO objects. Use the objects the throw them (let them get garbage collected). Don't try to reuse.
  6. For extra safety, make task-oriented objects like BO/Bean and DAO stateless as far as possible (by avoiding instance variables).
  7. Make shared objects read-only (immutable) as far as possible: For example, if you have a list of countries supported by your application, that list is not going to change. So, mark the reference as final and use immutable lists/maps (See: http://stackoverflow.com/questions/7713274/java-immutable-collections).

Java collections

The Java collection consists of Sets, Lists and Queues:

Lists

Lists can contain duplicates, even LinkedList. If you want to eliminate duplicates (automatically), use a Set-type. What's different between types of lists is the speed of certain operations and this is how to pick which one to use in a given situation.

ArrayList - dynamically sizing array. Fast random-read access, get() takes constant time. Adding and removing require shifting of the array elements in memory, however. When the size of the array must be increased due to addition, a new array of size 150% is allocated and the old array must be copied. The default, unspecified size (Java 4 through 7) is 10. Constructing it with more saves time if you know there will be more.

ArrayList is hugely expensive for remove operations and for add operations when the size allocated is used up.

Vector works like ArrayList, but is synchronized and therefore thread-safe—and slightly slower. Most programmers eschew this in favor of ArrayList since they want to synchronize explicitly anyway.

LinkedList - doubly linked list. Best for constant-time insertions and sequential access of elements. Finding a position in the array takes time proportional to the length of the list. The size penalty for the overhead grows considerably over that for ArrayList at, on a graph, almost a 45° angle. (Note: since late Java 6, no distinction between 32-bit and 64-bit is distinguishable—64-bit used to have even more overhead.)

—better for add and remove than ArrayList, worse for get and set operations. Use LinkedList if there are going to be few random accesses (get(), contains()) or many add or remove operations. See http://www.programcreek.com/2013/03/arraylist-vs-linkedlist-vs-vector/.

HashMap is like an ArrayList of key-value pairs, but it is not implemented within the framework of Java collections (it's not a set, list or queue). It is a Map. Keys in a map cannot occur in duplicates.

Sets

In a set, no duplicates are allowed. When adding, duplicates are removed automatically. The three most commonly used sets implementations are HashSet (fast), LinkedHashSet (order-preserving) and TreeSet (maintained sorted, slowest).

EnumSet - alternative to bit fields in C, for iteration over a set of flags.

HashSet - elements are unordered, held in a hash table. Good performance. Add, remove and contain operations have constant-time complexity.

LinkedHashSet - is a sort of hash table with a linked list running through it, maintaining the order of insertion, but not reordering new insertions respective to existing ones. Performance compromise between the above.

See http://www.programcreek.com/2013/03/hashset-vs-treeset-vs-linkedhashset/.

Queues

(Not today.)


Java maps

The Java map consists of HashMap, LinkedHashMap, TreeMap and Hashtable.

HashMap - makes no guarantee as to order, allows one null key and null values. Traversed using iteratory, entry set. (Inherits AbstractMap.)

LinkedHashMap - preserves the original insertion order, but is otherwise identical to HashMap.

TreeMap - uses natural or comparator-based ordering to maintain contents in-order. Null keys only allowed if comparator used and doesn't thrown an exception.

Hashtable - makes no guarantee as to order, disallows null keys and values, is synchronized and therefore expensive if you don't need that. Traversed using enumerator and iterator. (Inherits Dictionary.)


Java filepaths

You try to create a file. Where is it? Original, Windows code:

File child = new File(".././Java.txt");
  • getPath() —likely relative to current working subdirectory.
  • ..\.\Java.txt
  • getAbsolutePath() —fully qualified path, but in relationship to the current working subdirectory.
  • C:\Users\WINDOWS 8\workspace\Demo\..\.\Java.txt
  • getCanonicalPath() —full path from the filesystem's point of view.
  • C:\Users\WINDOWS 8\workspace\Java.txt

Converting String to InputStream

See here.


byte[] to String
byte[] aByte = new String( ".976" ).getBytes();
String propertyValue = new String( aByte );

...otherwise, aByte.toString() yields gobble-dee-gook.


Exceptions

... exist in checked and unchecked varieties. The original idea:

Unchecked exceptions represent defects in the application code, perhaps a null pointer, an invalid argument passed to a non-private method. These represent conditions that, generally speaking, reflect errors in logic and cannot be reasonably recovered from at runtime.

At least that was the theory in the 1990s.

Checked exceptions are invalid conditions in area outside immediate control of application code including invalid user input, database problems, network outages, absent files, etc.

They are subclasses of Exception.

Methods are obliged to establish a policy for all checked exceptions thrown by its implementation (either by passing the problem further up the stack or throwing again to be handled elsewhere).

If a client can reasonably be expected to recover from an exception, make it a checked one. If unreasonable, make it unchecked. Avoid unnecessary use of checked exceptions which place a burden on the programmer.


Exceptions, version 2
  1. Any exception that can be thrown by a method is part of the method's public programming interface.
  2. Methods calling such a method must know about the exceptions that the latter can throw and decide what to do about them.
  3. Runtime exceptions represent (only) problems that are the result of a programming solutions from which the calling method cannot be reasonably expected to recover or handle in any graceful or useful way. This would include dividing by zero, null-pointer references and indexing exceptions (attempting to access a list or array with an index outside the existing bounds of the data). Illegal arguments are also reasons to throw RuntimeException. Forcing code to check such exceptions reduces the clarity of the code.
  4. Moral of the story: If code cannot reasonably or usefully recover from an exception, then leave it as an unchecked exception. Otherwise, make it a checked exception.

                   ┌───────────┐
                   │ Throwable │
                   └───────────┘
                    /         \
                   /           \
          ┌───────┐          ┌───────────┐
          │ Error │          │ Exception │
          └───────┘          └───────────┘
           /  |  \           / |        \
          \_______/       \______/       \
                                      ┌──────────────────┐
          unchecked        checked    │ RuntimeException │
                                      └──────────────────┘
                                        /   |    |      \
                                       \_________________/

                                            unchecked

Java API exceptions

This is API theory: the right/best way to do things.

Returning null

This means the intent of the code is not explicit without looking at the JavaDocs, and so the worst option on our list.

Returning an Optional< T >

This makes the intent explicit compared to returning null. Of course, this requires Java 8.

Return a Guava's Optional< T >

For those of us who are not fortunate enough to have Java 8.

Returning one's own Optional< T >

If you don't use Guava and prefer to embed your own copy of the class instead of relying on an external library.

Returning a Try

Cook up something like Scala's Try, which wraps either (hence its old name, "Either") the returned bean or an exception. In this case, however, the exception is not thrown but used like any other object, hence there will be no performance problem.

Conclusion: when designing an API, one should really keep using exceptions for exceptional situations only.

A better piece of advice (not mine, but a quote I read somewhere):

"When designing an API, I use the "get vs. find rule." The API's user needs to know how to handle the absence of a result. A get is expected to always return a result while a find is not. And so when coding getX() it returns the result or throws an exception—such as llegalStateException—if there is not one. Where as, when coding findX() it returns a result if available or a null, or an empty collection, if there is not one."


Checked/unchecked exceptions

1. Throwable and Error classes should not be caught

Throwable is the superclass of all errors and exceptions in Java. Error is the superclass of all errors which are not meant to be caught by applications. Thus, catching Throwable would essentially mean that Errors such as system exceptions (e.g., OutOfMemoryError, StackOverFlowError or InternalError) would also get caught. The recommended approach is that an application should not try to recover from errors such as these. Therefore, Throwable and Error classes should not be caught. Only Exception and its subclasses should be caught.

Data errors such as encoding issues etc which are not known at programming time should be caught using this technique. However, catching Throwable such as InternalError or OutofMemoryError would not be of any help and should never be thrown.

Avoid writing code consisting of catching Throwable as general practice.

2. Throwable.printStackTrace(...) should never be called

One should avoid invoking printStackTrace() method on Throwable/Exception classes and instead use a logging framework.

3. Generic exceptions Error, RuntimeException, Throwable and Exception should never be thrown

The primary reason to avoid throwing generic Exceptions, Throwable and Error is that doing so prevents classes from catching the intended exceptions. A caller cannot examine the exception to determine why it was thrown and consequently cannot attempt recovery.

Catching RuntimeException is considered a bad practice. Throwing generic Exceptions/Throwable leads the developer to catch the exception at a later stage which usually leads to worse practices.

Do not throw a generic exception like RuntimeException. Do, however, throw a custom-rolled exception that inherits from RuntimeException.

4. Exception handlers should preserve the original exception

5. System.out or System.err should not be used to log exceptions

The primary reason one should avoid using System.out or System.err to log exceptions is that one might simply loose the important error message.

Checked exceptions!

One man's opinion...

It is an utterly failed experiment because it is designed around the totally flawed assumption that the service/library throwing the exception should decide which ones should be checked and which ones should not. In reality, only the caller knows which ones should be caught (usually none), and which ones should not.

6. Generally, whenever a library-method is called that throws a checked exception, just do:

try
{
  libraryObject.method();
}
catch( Exception e )
{
  throw new MyAppRuntimeException( e );
}

...to prevent this checked-exception idiocy from propagating like a virus and infecting the whole application.


Don't throw an instance of class Exception...

Throwing java.lang.Exception is bad practice...

Exception thrown explicitly by your code becomes impossible to discriminate from among other (unexpected) exceptions in a catch clause.

Better by far to pick a more specific exception, including manufacturing a proprietary one if there's nothing obviously suitable.


Reasons for resorting to a conditional...

...to think about and perhaps solve. Some are unavoidable—foisted upon one by someone else, some are code stench.

  1. Checking a value returned to me from code I own (null-pointer check stench)?
  2. Checking a value returned to me from code I do not own?
  3. Checking a parameter passed to me by code I own (control couple stench)?
  4. Checking a parameter passed to me by code I do not own?
  5. Checking my own state or attributes?
  6. Checking a value I set previously in this method?
  7. Checking the type of an exception thrown by code I own?
  8. Checking the type of an exception thrown by code I do not own?

How to close streams for sure

This code doesn't close streams although it's trying. It could throw an exception when one fails to close. If attempting to close fis fails, the code throws an exception and prints out a warning, but nothing is done to attempt to close fos.

FileInputStream  fis = null;
FileOutputStream fos = null;

try
{
  fis = new FileInputStream( "stuff-to-read.txt" );
  fos = new FileOutputStream( "stuff-put-out.txt" );
  ...
}
finally
{
  try
  {
    if( fis != null )
      fis.close();
    if( fos != null )
      fos.close();
  }
  catch( IOException e )
  {
    System.out.println( "Failed to close streams" );
  }
}

This code will do the trick, but it's a bit unsightly. It takes up a lot of space and obfuscates a simple thing.

InputStream  fis = null;
OutputStream fos = null;

try
{
  fis = new FileInputStream( "stuff-to-read.txt" );
  fos = new FileOutputStream( "stuff-put-out.txt" );
  ...
}
finally
{
  try
  {
    if( fis != null )
      fis.close();
  }
  catch( IOException e )
  {
    ;
  }
  try
  {
    if( fos != null )
      fos.close();
  }
  catch( IOException e )
  {
    ;
  }
}

JVM mind (share) map

Click to see full size.


Random in Java

Check out these claims when you get a chance.

import java.lang.reflect.Field;
import java.util.Random;

public class Entropy
{
  public static void main(String[] args) throws Exception
  {
    // extract the IntegerCache through reflection...
    Class< ? > clazz = Class.forName( "java.lang.Integer$IntegerCache");
    Field      field = clazz.getDeclaredField("cache");

    field.setAccessible( true );

    Integer[] cache = ( Integer[] ) field.get( clazz );

    // rewrite the Integer cache...
    for( int i = 0; i < cache.length; i++ )
      cache[ i ] = new Integer( new Random().nextInt( cache.length ) );

    // prove randomness...
    for( int i = 0; i < 10; i++ )
      System.out.println( ( Integer ) i );
  }
}

Reverse string
public class StringReverse
{
  private static final String[] FODDER =
                                { // palindromes except the first...
                                  "Off to the races...",
                                  "Madam I'm Adam",
                                  "A dog, a plan, a canal: pagoda",
                                  "A nut for a jar of tuna",
                                  "A Santa at NASA",
                                  "A slut nixes sex in Tulsa",
                                  "A car, a man, a maraca"
                                };

  private static String reverse( String string )
  {
    if( string.length() < 2 )
      return string;

    /* Algorithm: Grab everything after the first character and return
     * it followed by the (soon to be former) first character itself.
     */
    return reverse( string.substring( 1 ) ) + string.charAt( 0 );
  }

  public static void main( String[] args )
  {
    for( String string : FODDER )
    {
      String message = "String  " + string + " ";
      int TAB = 40, length = message.length();

      System.out.print( message );

      while( length++ < TAB )
        System.out.print( " " );

      System.out.println( " reversed is:  " + reverse( string ) );
    }
  }
}

Output:

String  Madam I'm Adam                   reversed is:  madA m'I madaM
String  Off to the races...              reversed is:  ...secar eht ot ffO
String  A dog, a plan, a canal: pagoda   reversed is:  adogap :lanac a ,nalp a ,god A
String  A nut for a jar of tuna          reversed is:  anut fo raj a rof tun A
String  A Santa at NASA                  reversed is:  ASAN ta atnaS A
String  A slut nixes sex in Tulsa        reversed is:  asluT ni xes sexin tuls A
String  A car, a man, a maraca           reversed is:  acaram a ,nam a ,rac A

Arrays.toString() minus the brackets

Arrays.toString( array ) surrounds the whole with "[ ... ]"—not what we want.

private String arrayToString( String[] array )
{
  StringBuilder sb    = new StringBuilder();
  boolean       first = true;

  for( String particle : array )
  {
    if( !first )
      sb.append( ' ' );

    sb.append( particle );
    first = false;
  }

  return sb.toString();
}

EarlyExitException is not EarlyExitException (symbol is not symbol)

Beware (duh!) that if you have a duplicate class, EarlyExitException, in your code and are building using a JAR that also has that symbol, uses and throws it, your code will not be catching it just because you happen also to have EarlyExitException. They are different and you get errors like

unreported exception EarlyExitException; must be caught or declared to be thrown

because EarlyExitException is not EarlyExitException.


Unsupported major.minor version 52.0

This happens when you've got code in your JAR, WAR or NAR compiled with a higher version of Java (in my case 8) for a higher version of Java (in my case, 8 though I wasn't specifying it by using this plug-in).

	<plugin>
		<groupId>org.apache.maven.plugins</groupId>
		<artifactId>maven-compiler-plugin</artifactId>
		<configuration>
			<source>1.7</source>
			<target>1.7</target>
		</configuration>
	</plugin>

The solution is to build everything with 1.7 (or whatever). Use Maven to clean out what's there before recompiling and packaging with this plug-on configuration in place.


Notes on Java serialization
public class SerializableClass implements Serializable
{
  private static final    long   serialVersionUID = 456778567857L;
  public                  String firstField       = "First Field";
  public transient static String secondField      = "Second Field";
  public transient final  String thirdField;      // unintialized
  public transient final  String fourthField      = "Fourth Field";
  private int                    privateField     = 99;

Notes

  1. serialVersionUID is explicitly defined to prevent InvalidClassException during deserialization. As the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations and can produce different results in different environments, beware.
  2. firstField will be serialized, and the default value can be overridden in subsequent classes that are serializing SerializableClass.java.
  3. secondField, thirdField and fourthField, being either transient static or transient final, will never be serialized. The values these will have will be restored at deserialization from whatever their values are in SerializableClass at the time it happens.
  4. privateField is private. It will be serialized, but can be read only through reflection.

Notes on JVM heap memory

Java thinks in terms of ordinary object pointers (OOPs) rather than native machine pointers (64-bit addresses in our day). These managed "pointers" are created such that the JVM can address up to 4-billion objects (not bytes, but full objects of arbitrary size). This is done via a phenomenon called compressed OOPs. See Java HotSpot™ Virtual Machine Performance Enhancements. See also Java Performance Tuning Guide.

The up-shot of this is that the JVM uses only 4-byte references (remember, these are not memory pointers). This means that there is a huge savings on 64-bit machines in terms of "pointer overhead." However, in this "express mode," you effectively only benefit from a -Xmx31Gb heap (though there's a huge savings in terms of what you think are pointers throughout your data: you save 4 bytes for each "memory" reference in your Java data objects).

In reality, the actual heap setting is something like -Xmx32Gb-1Mb because the consequence of graduating from OOPs to (64-bit) object references begins at about 1Mb before 32Gb.

64-bit (byte) addressing

Once your heap exceeds 32Gb nominally, you're in full, 64-bit land and your references begin to use 64-bits of reference (instead of the express OOP solution). Setting your heap somewhere between -Xmx32G - 1Mb and -Xmx38Gb will in effect reduce the amount of heap space because you've now lost space to the 8-byte (instead of 4-byte) memory references.

The JVM can manage about as much memory as you can throw at it, but it's much more efficient at doing it below 32Gb. There's a lost space between 32Gb-1Mb and almost 38Gb in which you get less heap than if using 31Gb (or 32Gb-1Mb). Beyond 38Gb, you're running in free and open territory because using 64-bit object references.

There's a non-zero effect upon garbage collection too. (Use -XX:+PrintGCDetails to see this impact.) Not having direct experience with this, I'll abstain for now from speculating on it.

Finally, it is not true that Java can't use more than 32Gb of memory. It's only that it uses it differently and that there is a lost grey area before 38Gb (depends on an application's peculiar object sizes just how wide this inefficiency actually is).


Notes on JVM garbage collection

These are the causes of the JVM garbage collection firing according to frequency in an average application.

Allocation Failure Application tried to make a new allocation and failed due to lack of available space in Young generation; hence Minor GC is required. On Linux, the JVM can trigger a GC if the kernel notifies there isn't much memory left via mem_notify.
GC Locker GC is started after all threads leave the JNI Critical region. For more information on JNI, refer to the Java Native Interface documentation website. GC is blocked when any thread is in the JNI Critical region and can start only when all of them outside of it.
G1 Evacuation Pause This is actual only for the G1 collector. It indicates that it is copying live objects from one set of regions (Young and sometimes Young + Tenured, which is called Mixed) to another set of regions.
G1 Humongous Allocation This is actual only for the G1 collector. Humongous is an allocation when its size is greater than 50% of one region size; the object then allocated in special space. Nevertheless, it also causes normal GC collection to get more (possibly continuous also) space for such objects.
CMS Initial Mark Initial mark phase of CMS, for more details, see Phases of CMS. It also triggers Young Space collection.
System.gc() There was a System.gc() call in the application code. You can start JVM with the -XX:+DisableExplicitGC flag to disable such behavior.
Adaptive Size Ergonomics Indicates you are using the adaptive heap size policy (ability to change Young and Tenured spaces size at runtime), enabled via the -XX:+UseAdaptiveSizePolicy flag. By default, it is enabled in the recent versions of JVM.
Allocation Profiler This is actual only for versions of Java before 8 and only when -Xaprof is set. It triggers just before JVM exits.
Heap Inspection GC was triggered by an inspection operation on the heap, most probably by the jmap tool with the -histo:live flag set.
Heap Dump GC was initiated before heap dump is made by some profiling instrument.
No GC Normally, you shouldn't see this reason. It was occurring in older Java versions, in case jstat command was started before any collection occurred. Other case is when jstat checks GC without any GC activity.
Last-ditch Collection When Metaspace (Java 8+) or PermGen (Java 7-) is full and you can't allocate a new object here, JVM first tries to clean it, triggering appropriate collector. If that's not possible, it then tries to expand it. If that doesn't work as well, it triggers Full GC with this cause name. Soft references are being cleaned during it as well.
Perm Generation Full Triggered as a result of an allocation failure in PermGen. Actual for Java versions prior to 8.
Metadata GC Threshold Triggered as a result of an allocation failure in Metaspace. Metaspace is a replacement for PermGen in Java 8+.
JvmtiEnv ForceGarbageCollection Something called the JVM tool interface function ForceGarbageCollection.

Notes on immutable classes

An immutable class is simply one whose objects, once they've been instantiated, are unmodifiable, i.e.: cannot be changed. These include String, most implementations of date and time classes and wrapper classes (c'est-à-dire Boolean, Short, Long, Double, Float. There are other examples such as File. Classes following the Singleton pattern are typically immutable. Enumerations are typically immutable (unless they've been badly coded).

Benefits of immutable classes:

  • as noted, the object never changes
  • their methods are thread-safe

Steps to creating an immutable class:

  1. Make all instance variables/fields private for no direct access.
  2. Initialize only using constructors.
  3. Make all instance variables/field final so they can't be changed without failing compilation.
  4. If providing for cloning, make it a deep-clone, that is, one that does not copy object references including
    • the object itsef
    • any object internal to the object
  5. Provide no setter methods.
  6. Provide no getter method that fails to deep-clone the object it returns.
  7. Define the class as final in order that it not be extendable.

Matching groups in regular expressions in Java
public void funWithRegularExpressions( final String patient_local_id )
{
  // 'patient_local_id' contains "Mercy_Hospital:665892"
  String facilityName, separator, facilityId;
  Pattern pattern;
  Matcher matcher;

  pattern      = Pattern.compile( "^([\\w\\s]+)\\W.+$" );
  matcher      = pattern.matcher( patient_local_id );
  facilityName = ( matcher.find() ) ? matcher.group( 1 ) : patient_local_id;

  pattern      = Pattern.compile( "^[\\w\\s]+(\\W).+$" );
  matcher      = pattern.matcher( patient_local_id );
  separator    = ( matcher.find() ) ? matcher.group( 1 ) : patient_local_id;

  pattern      = Pattern.compile( "^[\\w\\s]+\\W(.+)$" );
  matcher      = pattern.matcher( patient_local_id );
  facilityId   = ( matcher.find() ) ? matcher.group( 1 ) : patient_local_id;

  System.out.println( "Facility name: " + facilityName );
  System.out.println( "    Separator: " + separator );
  System.out.println( "  Facility id: " + facilityId );
}

Output:

Facility name: Mercy_Hospital
    Separator: :
  Facility id: 665892

Strange string arithmetic...

In a twist right out of Paul Simon's, When Numbers Get Serious (read second verse), I just encountered this weirdness today. I guess I don't do stuff like this very often, but I was surprised to see it and I struggled to find wording in Google to find its explanation:

1. int x = 1;
2. System.out.println( "x = " + x );
3. System.out.println( "x+1 = " + x+1 );

Output is:

x = 1
x+1 = 11

Freaky. I was doing this in some code I wrote.

So, what's going on? On line 3, the + operator is string concatenation rather than arithmetic addition. Operator precedence assures that x's value is converted to a string, concatenated "x+1 = ", then the value 1 is converted to a string and concatenated to the previous string.


Consuming UNIX .so files from a project...

Ordinarily, one consumes a .so on the path indicated by LD_LIBRARY_PATH. However, this isn't necessarily set to anything especially when running or debugging in Eclipse, IntelliJ IDEA, etc.

Here's something I tried with success for consuming libsigar-amd64-linux.so:

  1. Copy the shared object to project-foldersrc/main/resources.
  2. Edit run/debug configurations and add an environment variable:
    LD_LIBRARY_PATH=/home/russ/dev/cassandra/target/classes
    
    This works because, when built, the target subdirectory contains a classes subdirectory to where, in addition to compiled Java class files, anything put into the src/main/resources subdirectory gets copied.

This solution is a bit volatile, however, in that you must maintain this configuration when you run. Run/Debug Configurations in IntelliJ are notoriously volatile. Also, this does nothing for the final Java product JAR and you'll have to copy the shared object to wherever LD_LIBRARY_PATH points before launching your Java application.

I've dealt with this before, but in specific environments and always tentatively. Surely there's something better and more correct to say.


Handling exceptions in Java—best practices...

See this article. The main points, however, are:

  1. Clean up resources in a finally block
    File file = new File( <pathname> );
    
    try
    {
      FileInputStream inputStream = new FileInputStream( file );
      // do something with inputStream...
    }
    catch( Exception e )
    {
      // handle exception...
    }
    finally
    {
      inputStream.close();
    }
    
    or use a (Java 1.7) try-with-resource statement, which will automatically close the resources listed (assuming they implement AutoCloseable:
    File file = new File( <pathname> );
    
    try ( FileInputStream inputStream = new FileInputStream( file ); )
    {
      // read the file...
    }
    catch( FileNotFoundException e )
    {
      // handle FileNotFoundException...
    }
    catch( IOException e )
    {
      // handle IOException...
    }
    
  2. Prefer specific (custom) exceptions in your application.

  3. Document the exception the method specifies in its signature by means of @throws in the Javadoc.

  4. Throw exceptions with descriptive messages, e.g.:
    throw new Exception( "This is a useful descriptive message for developers and users!" );
    
  5. Catch the most specific exception first. Most IDEs enforce this by noting "unreachable code."

  6. Don't catch Throwable. This catches errors too that the JVM intends that the application not handle (because they cannot be handled).

  7. Don't ignore exceptions. IntelliJ stops bugging you about this if you define catch( Exception ignored ). This isn't good practice.

  8. Don't log then rethrow; this writes multiple messages for the same exception. If additional information needed, wrap in a custom exception, then rethrow.

  9. Wrap the exception caught and consume it, if by wrapping it in a custom exception (especially standard ones).

SQL timestamp for "now"...

This tutorial on Date, Time and Timestamp is elucidating: https://alvinalexander.com/java/java-timestamp-example-current-time-now


Updating the installed Java

Building at home, I get:

russ@gondolin ~/sandboxes/cassandra-ps-index.clustering_feature.dev/code/cassandra-ps-index $ mvn package
.
.
.
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.2:compile (default-compile) on project cassandra-ss-index-plugin: Compilation failure
[ERROR] No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?
[ERROR] -> [Help 1]

This is because I have a JRE instead of a JDK, which is what happens by default on a new Linux installation, which is what I have (Linux Mint 18.2 Sonya) since my box sort of exploded a few weeks back. This will fix it, although the alternatives thing never reveals to my satisfaction that I've fixed it:

russ@gondolin ~ $ sudo update-alternatives --config java
There is only one alternative in link group java (providing /usr/bin/java): /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
Nothing to configure.
russ@gondolin ~ $ sudo apt-get install openjdk-8-jdk
russ@gondolin ~ $ sudo update-alternatives --config java
There is only one alternative in link group java (providing /usr/bin/java): /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
Nothing to configure.

Yeah, looks the same to me. The only way I could tell that things were going to work was:

russ@gondolin ~ $ cd /usr/lib/jvm/java-8-openjdk-amd64/
russ@gondolin /usr/lib/jvm/java-8-openjdk-amd64 $ ll
total 28
drwxr-xr-x 7 root root 4096 Nov 14 08:34 .
drwxr-xr-x 3 root root 4096 Nov  8 06:28 ..
lrwxrwxrwx 1 root root   22 Oct 27 16:51 ASSEMBLY_EXCEPTION -> jre/ASSEMBLY_EXCEPTION
drwxr-xr-x 2 root root 4096 Nov 14 08:34 bin
lrwxrwxrwx 1 root root   41 Jul 27 20:31 docs -> ../../../share/doc/openjdk-8-jre-headless
drwxr-xr-x 3 root root 4096 Nov 14 08:34 include
drwxr-xr-x 5 root root 4096 Nov  8 06:28 jre  # not comforting...
drwxr-xr-x 3 root root 4096 Nov 14 08:34 lib
drwxr-xr-x 4 root root 4096 Oct 25 19:41 man
lrwxrwxrwx 1 root root   22 Oct 27 16:51 THIRD_PARTY_README -> jre/THIRD_PARTY_README
russ@gondolin /usr/lib/jvm/java-8-openjdk-amd64 $ find . -name '*tools*'
./lib/tools.jar                               # ah, now we know...
russ@gondolin ~/sandboxes/cassandra-ps-index.clustering_feature.dev/code/cassandra-ps-index $ mvn package
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.778 s
[INFO] Finished at: 2017-11-14T08:44:19-07:00
[INFO] Final Memory: 43M/357M
[INFO] ------------------------------------------------------------------------

Custom exceptions best practice
  1. Always provide a benefit, though this might be slim, like funneling everything through a common point.
  2. Following the naming convention of ending the class name by -Exception.
  3. Furnish JavaDoc that explains it all (see below).
  4. Furnish a constructor that includes the exception's cause.
    /**
     * This exception wraps all checked exceptions and enriches them
     * with a custom error code. You can use this code to retrieve
     * localized error messages and to link to our online documentation.
     */
    public class MyBusinessException extends Exception
    {
      public void wrapException( String input ) throws MyBusinessException
      {
        try
        {
          // do something
        }
        catch( NumberFormatException e )
        {
          throw new MyBusinessException( "A message that describes the error.",
                                e,
                                ErrorCode.INVALID_PORT_CONFIGURATION );
        }
      }
    }
    

HttpURLConnection "keep alive"...

...and some comparison to OkHttpClient.

The problem is, should I attempt to write my own pool of HTTP connections to improve performance when consuming the JDK's own HttpURLConnection?

Other questions to answer include:

  • Is OkHttpClient superior to HttpURLConnection?
  • Does it behoove me to provide a pool for HttpURLConnection or OkHttpClient?

Notes

OkHttpClient

While Android users have abandoned HttpURLConnection for OkHttpClient, and also some non-Android users too, this package does not appear on the face of my own experience to improve performance despite claims that it offers its own connection pooling.

What OkHttpClient clearly offers that is superior to HttpURLConnection is the cleaner, more easily understood interface and easier readability of a modern library. It's always simpler to write a decent interface when you have so many older and poorer ones to compare to.

Conclusion

It appears that HttpURLConnection offers pooling in its underlying socket implementation because of this, there really isn't any way to intervene in that implementation since you don't instantiate it, to wit, multiple instances of it. It's impossible to do that. It appears, similarly, that OkHttpClient is the same.

The last article above makes the observation that, while it's possible to increase the number of connections to keep alive, 10, 20 or 50 produce no visible improvement in the number of out-going requests. It also observes that switching to the Apache HTTP client, whose interface is notoriously changed every release (and you have to recode), the number of out-going requests increased threefold with no fine-tuning.

The Apache HTTP client, like OkHttpClient also has a better API than the original JDK client.

Finally, the last article, which is the most lucid and intact collection of observations than any of the others, urges one not to call HttpURLConnection.disconnect(), increase the number of connections in the pool and drain both the input- and error streams.


ThreadPoolExecutor...

The thread pool contained inside the ThreadPoolExecutor can contain any number of threads. The number of threads in the pool is determined by variables establish at construction:

  • corePoolSize and maxPoolSize. If fewer than corePoolSize threads are created in the the thread pool when a task is delegated to the pool, then a new thread is created, even if idle threads exist in the pool.
  • If the internal queue of tasks is full, and corePoolSize threads or more are running, but fewer than maxPoolSize threads are running, then a new thread is created to execute the task.
  • Once the number of threads reaches maxPoolSize, and all threads are busy when a new task is submitted, if a handler is registered, then that task is rejected and, the handler takes over. See RejectedExecutionHandler.
  • For RejectedExecutionHandler, this can be a very bad idea because it's prone to dead-lock since all the threads in the pool may have died before what you put into the queue is visible. This can be mitigated using a keep-alive delay.


UnsupportedOperationException when adding one list to another

This just bit me (after years writing in Java). It took me some serious head-scratching and Googling to figure it out. The secret is recounted in verbiage only if you understand "Returns a fixed-size list backed by the specified array." That doesn't really jump out at me, but there it is.

List< String > list1 = Arrays.asList( "this", "that", "and", "the", "other" );
List< String > list2 = new ArrayList();
list2.add( "something else" );
list1.addAll( list2 );
-- boom! --

It turns out that Arrays.asList() returns a fixed-size list backed by an array and it's an "unknown UnsupportedOperationException" to attempt to modify its size (maybe other write operations; I didn't try too hard). On the other hand, this works:

List< String > initialList = Arrays.asList( "this", "that", "and", "the", "other" );
List< String > list1 = new ArrayList();
list1.addAll( initial );
List< String > list2 = new ArrayList();
list2.add( "something else" );
list1.addAll( list2 );
-- no boom. --

Java versions through recent times

Check out Trisha Gee's article on Java 11 and IntelliJ IDEA.

Also, her article on the whole Java-version mess: Using Java 11 in Production: Important Things to Know.


JVM heap memory: going over 32G, 8-byte/64-bit references

Once application heap settings reach 32G, there are problems. See this article.

In summary, under 32G Java (object) memory references take only 4 bytes. Over 32G, references take 8 bytes. From 32G to 37/38G is a zone that reduces the total memory available because 20% of the heap is used to object references. The exact spot where the JVM switches over to using (true) 8-byte (64-bit) references is XMX32767M, which is 1M less than a full 32G.


Sorting out JNI issues

It is very difficult to troubleshoot JNI class loader issues. The only way to determine if it's a class loader issue is to eliminate all other UnsatisfiedLinkError cases first. If the code looks correct and is loading the correct version of the native library without errors, including the correct bitness package for the JRE, but is failing when creating the library context, then the only remaining explanation is class loader issues. At that point, the environment must be looked at to see where the offending .jar is loaded from. If this is a web application, and the JAR is loaded from a child class loader (i.e., from the web application's WEB-INF/lib directory), then that could point the way. In Java web-application environments, you have to load the native library and classes from a higher-level parent class loader, not from the individual web-application child class loaders.


Running JVM for remote debugging...

...from the likes of IntelliJ IDEA or Eclipse.

OpenJDK: $ java    -agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n
Oracle:  $ java -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y

Once the process comes up, you can adjust settings in Edit run configurations... for the port number, which you can choose (here 8000, but it can be anything).


Hermetization: not leaking state

See discussion here.


Variable-length arguments...

See discussion here.


Slurping a stream...

See discussion here.


Per-thread local store

See discussion here.


How to get the line number in the caller

This easily comes up as soon as logging is pushed down from one method (conveniently) into submethods since logging reports line numbers, but a submethod can't give an accurate location.

Of course, there are other problems this solution doesn't solve—like the fact that, if you've set to number lines in log4j.xml (e.g.: see :%L and comment below),

log4j.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration debug="false">

  <appender name="console" class="org.apache.log4j.ConsoleAppender">
    <layout class="org.apache.log4j.EnhancedPatternLayout">
      <!-- Produces: 2019-08-02 07:44:28 TRACE c.i.s.MyMethod:248 - (whatever message...) -->
      <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1.}:%L - %m%n" />
    </layout>
  </appender>

  <root>
    <level value="TRACE" />
    <appender-ref ref="console" />
  </root>

</log4j:configuration>

...then there will be the wrong line number reported (at very least, confusingly) no matter what your new message says when it's fixed using this solution.

/* Do this to get the current line number to pass
 * down so logging submethod has it right.
 */
logTrace( Thread.currentThread().getStackTrace()[ 1 ].getLineNumber(), ... )

This has got to be somewhat expensive too, but it does avoid the instantiation of a new exception (to get Exception.printStackTrace(), etc.).


ThreadLocal (TLS)

Here's how to do thread-local store in Java. Integer, below, could be anything (including an instance of a very complex class hierarchy).

  private static ThreadLocal< Integer > tls = new ThreadLocal<>();

  public static ThreadLocal< Integer > getTls() { return tls; }

  @Test
  public void test()
  {
    tls.set( 99 );
    int x = tls.get(); System.out.println( "  x = " + x );
    int y = tls.get(); System.out.println( "  y = " + y );

    tls.remove();
    tls.set( 543 );
    int z = tls.get(); System.out.println( "  z = " + z );

    tls.set( null );
    tls.set( 963 );
    int a = tls.get(); System.out.println( "  a = " + a );
    int b = tls.get(); System.out.println( "  b = " + b );
    tls.remove();

    int c = tls.get(); // kaBOOM!
  }

Output:

  x = 99
  y = 99
  z = 543
  a = 963
  b = 963

java.lang.NullPointerException
    at com.windofkeltia.tls.ThreadLocalTest.test(ThreadLocalTest.java:74)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    .
    .
    .
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)

Alternately, of course...

    ...
    int b = tls.get(); System.out.println( "  b = " + b );
    tls.remove();

    try
    {
      int c = tls.get();
    }
    catch( NullPointerException e )
    {
      System.out.println( "You can catch this." );
    }
  }
  x = 99
  y = 99
  z = 543
  a = 963
  b = 963
You can catch this.

Notes

  • The thread-local store is created as static; there is no way to fetch a reference to it from the thread itself.
  • To fetch it, you must either pass the static reference down or provide a static accessor (getter); code in any other class may freely manipulate the TLS' value including destroy it.
  • As illustrated, once remove() or set( null) has been called, the store is gone for any practical use; you must not call get() without first resetting the value to something valid (as illustrated here).
  • You should call remove() at some point before the thread is abandoned; if you don't, and your TLS resource is complex (i.e.: on the heap), you'll leak memory.

java.nio.file.Path{s}

Useful if minimal set of methods to break a filesystem path up into usable bits.

Path path     = Paths.get( "src/test/resources/fodder/xml-samples/bundle.xml" );

Path filename = path.getFileName();      // bundle.xml
Path absolute = path.toAbsolutePath();   // /home/russ/dev/fhir-json-xml/src/test/resources/fodder/xml-samples/bundle.xml
Path parent   = path.getParent();        // src/test/resources/fodder/xml-samples
Path subpath  = path.subpath( 2, 4 );    // resources/fodder
int  count    = path.getNameCount();     // 6

System.out.println( parent.toString() ); // (prints:) src/test/resources/fodder/xml-samples

How to determine the width of an integer...

...or, in other words, the number of places it occupies, the length of an array or string needed to hold it, space in a table, etc.

Obviously, the most straightforward way would be to turn it into a string, then measure the latter's length, but that's very expensive. There are several other ways that are much cheaper. This one isn't the very least expensive, however, it rejoices in being the simplest and most succinct:

int number = (whatever);
int numberOfDigitsInNumber = ( int ) Math.log10( number ) + 1;

Example outcome:

                number = 4923
numberOfDigitsInNumber = 4

The nature of Enumeration< ? >

An Enumeration< String >, used for example, in conjunction with methods of HttpServletRequest, is a "one-shot collection" in terms of being able to be traversed.

Once traversed as below, ...

import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.NoSuchElementException;

import org.junit.Test;

public class EnumerationTest
{
  @Test
  public void test()
  {
    List< String > headerNames = new ArrayList<>();
    headerNames.add( "ContentType" );
    headerNames.add( "Accept" );

    Enumeration< String > headers = Collections.enumeration( headerNames );

    try
    {
      // traverse 'headers' to see what's in this collection...
      while( headers.hasMoreElements() )
        System.out.println( headers.nextElement() );

      // 'headers' is no longer useful for traversal--it is "dead" now
    }
    catch( IllegalArgumentException e )
    {
      e.printStackTrace();
    }
    catch( NoSuchElementException e )
    {
      e.printStackTrace();
    }
  }
}

...what's stored in headers can not be "reset" in order to get traversed again as there are only two useful methods, both used above, hasMoreElements() and nextElement(). If a more functional working copy is required, then create a List from it thus:

// take 'headers' from the code in the test above...
ArrayList headerNameList = Collections.list( headers );

for( String header : headerNameList )
  System.out.println( header );

// 'headerNameList' remains traversable after this point...

Both snippets of code here print the same output.


Dressing a string in floating-point...

The premise is that you have a string that could have anything in it, but it likely has some digits. Let's say, "<2" or "0.5+" and you are interested in the numeric stuff. Use this to remove (the "<" and "+" from the examples here and infinite others):

final String VALUE          = (some example as above);
final String ONLY_NUMERICS  = VALUE.replaceAll( "[^\\d.-]", "" );

The result would be (for the two examples cited) "2" and "0.5".


Using the Decorator pattern to rename and/or dress up superclass

"Renaming" XyzClass with XClass.

I have long wondered about "renaming" classes. In C, there is typedef that would allow me to use, for example, something called XyzPatient in my code as XPatient without me having to create a class formally.

#define IPatient IxmlPatient

In Java, I can do this:

Code from Xyz library:
public class XyzPatient
{
  public String name;

  @Override
  public String toString()
  {
    return "{ " + "name: \"" + name + "\" }";
  }
}
Code from my application's shim:
public class XPatient extends XyzPatient
{
}
Code from my application:
public class PatientTest
{
  @Test
  public void test()
  {
    XPatient patient = new XPatient();
    patient.name = "Jackson";
    System.out.println( patient );
  }
}

Formally speaking, this doesn't walk too far down the path of "decoration" for it only renames the class—it doesn't add anything to it. However, I have deceived you: I don't want to decorate the superclass with additional functionality, but only change its name.

Running test() produces:

{ name: "Jackson" }

But, I confess that I don't know how far this goes. I know that, in the past, I have had trouble doing much with class XPatient above. This example works well enough, but, when I have attempted to roll a class from a third-party library whose names I don't like (usually because they collide with classnames already in use in my code) into a "naked" decorator of this sort, I have had some trouble.

One problem I know about is when the extending class doesn't offer a constructor that matches one of the extended class' constructors. For example, let's conjecture a superclass, Pojo, underneath the library's XyzPatient, that offers an alternative constructor that we wish to make use of:

More complete code from Xyz library:

Note the non-default constructor. What's with toString()? just that XyzPatient.toString() uses Pojo.toString(), but lops off the last curly brace before adding its own field(s).

This example is a little stretched using field ____ to name the extending POJO, but it serves to complicate the example just enough to make it useful.

public class Pojo
{
  public String ____;

  public Pojo() { }

  public Pojo( final String elementName )
  {
    ____ = elementName;
  }

  @Override
  public String toString()
  {
    return "{\n  ----: \"" + ____ + "\" }";
  }
}

public class XyzPatient extends Pojo
{
  public String name;

  @Override
  public String toString()
  {
    StringBuilder sb   = new StringBuilder();
    String        base = super.toString();
    sb.append( "{ " ).append( base.substring( 0, base.length()-1 ) ) );
    sb.append( "name: \"" ).append( name ).append( name ).append( "\"\n" );
    sb.append( "}" );
    return sb.toString();
  }
}
Code from my application's shim:
public class XPatient extends XyzPatient
{
  public XPatient( final String name ) { super( name ); }
}
Code from application test:

Note the use of the non-default constructor.

public class PatientTest
{
  @Test
  public void test()
  {
    XPatient patient = new XPatient( "patient" );
    patient.name = "Jackson";
    System.out.println( patient );
  }
}

Running test() produces:

{
  ____: "patient"
  name: "Jackson"
}

Enum reflection in Java

I wrote and tested this, then abandoned it for a better way, but I spent enough time on it that I didn't want to lose it. The idea was to discover the expression-language scope field inside PropertyDescriptor with the value NONE and replace it with FLOWFILE_ATTRIBUTES.

import java.lang.IllegalAccessException;
import java.lang.NoSuchFieldException;
import java.lang.reflect.Field;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.expression.ExpressionLanguageScope;
import org.apache.nifi.processor.AbstractProcessor;

public class CustomProcessor extends AbstractProcessor
{
  ...
  public static final PropertyDescriptor BASE_SQL_QUERY = new PropertyDescriptor.Builder()
      .name( "Base SQL Query" )
      .displayName( "Base SQL Query" )
      .description( "Base SQL query." )
      .required(true)
      .addValidator( StandardValidators.NON_EMPTY_VALIDATOR)
      .expressionLanguageSupported( true /*ExpressionLanguageScope.FLOWFILE_ATTRIBUTES*/ )
      .build();

  static
  {
    PropertyDescriptor descriptor = BASE_SQL_QUERY;
    try
    {
      Field field = descriptor.getClass().getDeclaredField( "expressionLanguageScope" );
      field.setAccessible( true );
      Object value = field.get( descriptor );
      ExpressionLanguageScope scope = ( ExpressionLanguageScope ) value;
      if( scope == ExpressionLanguageScope.NONE )
        field.set( descriptor, ExpressionLanguageScope.valueOf( "FLOWFILE_ATTRIBUTES" ) );
      field.setAccessible( false );
    }
    catch( NoSuchFieldException e )
    {
      throw new RuntimeException( e );
    }
    catch( IllegalAccessException e )
    {
      throw new RuntimeException( e );
    }
  }

The reason I didn't end up needing this is because of the existence of backward-compatibility code in Apache NiFi:

private CustomProcessor processor = new CustomProcessor();
private TestRunner      runner    = TestRunners.newTestRunner( processor );
runner.setValidateExpressionUsage( false );

This stopped modern NiFi test code from requiring the modern mechanism of Expression Language scope (in place of the old Boolean true/false that the property supported using NiFi Expression Language). Running on later versions of NiFi doesn't crash, so I'm not tempted to hack the value in.


Steps to upgrade Java on CentOS (Red Hat, etc.)
$ sudo yum install java-11
$ sudo alternatives --config java

Then, select Java 11 from the alternatives menu.