Table of Contents

Java

Effective Java

Java internals

Java Native Interfaces

  • CNI is the alternative to JNI in case you use JCG. It allows you to write classes in C++ (which can be extended by Java) and call native functions.
  • JNA allows to call native functions dynamically at runtime without JNI code generation. The signature for native method is generated from Java interface with automatic mapping for all data types (primitives, strings, structures, unions, arrays, function pointers for callbacks from native code to Java, varargs).
  • JNAerator – parses C / C++ & Objective-C headers and generates the corresponding BridJ, JNA and Rococoa Java interfaces.
  • Дорог ли native метод? "Секретное" расширение JNI – недокументированная возможность HotSpot JVM 7 для ускоренного вызова простых JNI методов

Java code quality control

  • UCDetector – Unnecessary Code Detector Eclipse plugin
  • Checkstyle – Eclipse plugin for Check stylecode analyzer
  • FindBugs – Eclipse plugin for static analysis to look for bugs in Java code

Reactive programming

Java and TCP/IP stack

Questions answered

What Java decompiler is the best?

What are the faster alternatives to Java Collections?

What is faster alternative to java.util.Stack?

java.util.Stack is known to be based on java.util.Vector and thus is slow. What are the faster alternatives?

From java.util.Stack appropriate data structure:

Use java.util.Deque interface implementations (push(), peek() and remove() operations). java.util.ArrayDeque does not support null elements in contrast to java.util.LinkedList. Apache org.apache.commons.collections.ArrayStack is better then java.util.ArrayDeque, but it is not generalized (check Using generics with commons collections).

How can I split/partition a list in multiple lists (chunks) of given size?

If the list is not going to be mutated while processing of chunks the most effective is to create a view over the original list using List#subList(int fromIndex, int toIndex)

ListUtils#partition(List<T> list, int size also works in effective way and is based on List#subList(int, int):

import org.apache.commons.collections4.ListUtils;
 
List<List<?>> chunkedList = ListUtils.partition(sourceList, chunkSize);

How to instantiate empty java.util.Enumeration instance?

import org.apache.commons.collections4.FluentIterable;
 
Enumeration e = FluentIterable.<String> empty().asEnumeration();
import org.apache.commons.collections4.IteratorUtils;
 
Enumeration e = IteratorUtils.asEnumeration(Collections.emptyListIterator());

How to expand variables in a string?

import org.springframework.util.PropertyPlaceholderHelper;
 
PropertyPlaceholderHelper helper = new PropertyPlaceholderHelper("${", "}");
String interpolatedValue = helper.replacePlaceholders(stringToBeInterpolated , System.getProperties());

How to match given path against Ant path pattern?

import org.springframework.util.AntPathMatcher;
 
new AntPathMatcher().match(pattern, path); // e.g. match("/**/user/*", "/global/user/12");

How to escape HTML string?

URI does not escape plus (+) in query

For example ?q=word+word should become ?q=word%2bword.

The challenge for URI is that once it receives query as a e.g. constructor argument, it's too late to understand the semantic of it, because query is already a string with all key-value pairs joined. As + is a special character as to RFC 2396 it does not need to be escaped. For example, consider query ?key+=+val which is interpreted as ?key = val at server side and that is perhaps the desired effect. Other builders work on higher semantic level (one can pass query parameter name and value separately), thus can do smarter escaping (at least to control it). Nevertheless they could have different views on what should be escaped:
import org.springframework.web.util.UriComponentsBuilder;
import javax.ws.rs.core.UriBuilder;
 
System.out.println(UriComponentsBuilder.fromHttpUrl("http://host.com/path").queryParam("q", "my+zip%20/?&").build().encode().toUri());
System.out.println(UriComponentsBuilder.fromHttpUrl("http://host.com/path{suffix}").path("{sub}").queryParam("q", "{value}").buildAndExpand("/group%31?", "/id%41?", "my+zip%20/?&").encode().toUri());
System.out.println();
System.out.println(UriBuilder.fromUri("http://host.com/path").queryParam("q", "my+zip%20/?&").build());
System.out.println(UriBuilder.fromUri("http://host.com/path{suffix}").path("{sub}").queryParam("q", "{value}").build("/group%31?", "/id%41?", "my+zip%20/?&"));

produces output:

http://host.com/path?q=my%2Bzip%2520/?%26
http://host.com/path/group%2531%3F/id%2541%3F?q=my%2Bzip%2520/?%26

http://host.com/path?q=my%2Bzip%20%2F?%26
http://host.com/path%2Fgroup%2531%3F/%2Fid%2541%3F?q=my%2Bzip%2520%2F?%26

How to implement timeout for socket write() operation?

The problem is that calling Thread#interrupt() on a blocked in the read thread has no effect (see Interrupting a thread that waits on a blocking action?).

The solution is either launch a separate thread as watchdog or use non-blocking I/O: register selector for OP_WRITE events and select with timeout.

import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
 
final long WRITE_TIMEOUT_MS = 2000; // 2 seconds
 
SocketChannel channel = SocketChannel.open();
Selector selector = Selector.open();
 
channel.connect(new InetSocketAddress());
channel.configureBlocking(false); // switch to non-blocking after connection has succeeded
channel.register(selector, SelectionKey.OP_WRITE);
 
while (true) {
    int readyChannels = selector.select(WRITE_TIMEOUT_MS);
 
    if (readyChannels == 0) {
        continue;
    }
 
    for (Iterator<SelectionKey> iter = selector.selectedKeys().iterator(); iter.hasNext();) {
        SelectionKey key = iter.next();
 
        if (key.isValid() && key.isWritable()) {
            // a channel is ready for writing
            channel.write(buffer);
        }
 
        // remove the key thus marking it as processed:
        iter.remove();
    }
}

Read error response body in Java

Java HttpURLConnection returns body input stream via URLConnection#getInputStream() if HTTP response code was 2xx or 3xx, and HttpURLConnection#getErrorStream() otherwise.

getInputStream() can throw the exception which was remembered during negotiation phase.

When output streaming is enabled, authentication and redirection cannot be handled automatically (check docs/api/java/net/HttpURLConnection.html#HttpURLConnection#setFixedLengthStreamingMode%28int%29), which results an exception when trying to read or write a body.

Headers like Origin or Content-Length cannot be set on java.net.HttpURLConnection

If one tries to set the given header like this:
connection.setRequestProperty("Origin", "localhost");

it has no effect.

The solution is to set the following system property:
-Dsun.net.http.allowRestrictedHeaders=true

Sending / receiving multipart messages

Library Can read/unmarshall multipart message Can create / marshall multipart message
Apache mime4j :YES: :YES:
Apache HTTP client :NO: :YES:
Apache FileUpload :YES: :NO:
Spring :YES: via Apache FileUpload or Servlet 3.0 API :YES: in Spring 5 using reactive API (MultipartHttpMessageWriter)

Sending the message from prepared message template:

multipart.txt

--SgkN_pfgxWH2sRuHgygqYkEQgctzP9HK0s5
Content-Disposition: form-data; filename="text-part"
Content-Type: text/plain; charset=UTF-8

This is a message!
--SgkN_pfgxWH2sRuHgygqYkEQgctzP9HK0s5--
  • Spring RestTemplate

    import org.springframework.http.HttpEntity;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.client.RestTemplate;
     
    import org.apache.commons.io.IOUtils;
     
    private void requestMultipartRestTemplate() throws URISyntaxException, IOException {
        RestTemplate restTemplate = new RestTemplate();
     
        byte[] message = IOUtils.toByteArray(getClass().getClassLoader().getResourceAsStream("multipart.txt"));
     
        HttpHeaders httpHeaders = new HttpHeaders();
     
        httpHeaders.add(HttpHeaders.CONTENT_TYPE, "multipart/form-data; boundary=SgkN_pfgxWH2sRuHgygqYkEQgctzP9HK0s5");
        httpHeaders.setContentLength(message.length);
        httpHeaders.setAccept(Collections.singletonList(MediaType.MULTIPART_FORM_DATA));
     
        ResponseEntity<byte[]> httpResponse = restTemplate.postForEntity(
                    new URI("http://host.com/path"),
                    new HttpEntity<>(message, httpHeaders), byte[].class);
     
        System.out.println(httpResponse.getStatusCode());
        System.out.println(IOUtils.toString(httpResponse.getBody(), "UTF-8"));
    }
  • Java URLConnection

    import org.springframework.http.HttpHeaders;
     
    import org.apache.commons.io.IOUtils;
     
    private static void requestMultipartURLConnection() throws URISyntaxException, IOException {
        byte[] message = IOUtils.toByteArray(getClass().getClassLoader().getResourceAsStream("multipart.txt"));
     
        HttpURLConnection connection = (HttpURLConnection) new URL("http://host.com/path").openConnection();
     
        connection.setRequestMethod("POST");
        connection.setDoOutput(true);
     
        connection.setRequestProperty(HttpHeaders.CONTENT_TYPE, "multipart/form-data; boundary=SgkN_pfgxWH2sRuHgygqYkEQgctzP9HK0s5");
        connection.setRequestProperty(HttpHeaders.CONTENT_LENGTH, Integer.toString(message.length));
     
        try (OutputStream os = connection.getOutputStream()) {
            IOUtils.write(message, os);
        }
     
        System.out.println(connection.getResponseCode() + " " + connection.getResponseMessage());
     
        InputStream is = null;
        try {
            is = connection.getErrorStream();
            if (is == null) {
                is = connection.getInputStream();
            }
     
            System.out.println(IOUtils.toString(is, "UTF-8"));
        }
        finally {
            IOUtils.closeQuietly(is);
        }
    }

Constructing and sending the message on the fly using Apache HTTP client:

Apache HTTP client

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
 
import org.apache.commons.io.IOUtils;
 
private static void requestMultipartApacheClient() throws URISyntaxException, IOException {
    HttpPost httpPost = new HttpPost("http://host.com/path");
    MultipartEntityBuilder multipartBuilder = MultipartEntityBuilder.create();
 
    httpPost.setEntity(multipartBuilder.addTextBody("text-part", "This is a message!", ContentType.TEXT_PLAIN).build());
 
    CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
 
    System.out.println(httpResponse.getStatusLine());
    System.out.println(IOUtils.toString(httpResponse.getEntity().getContent(), StandardCharsets.UTF_8));
}

Receiving using Apache FileUpload:

Apache FileUpload + Spring

import org.apache.commons.fileupload.MultipartStream;
import org.apache.commons.lang3.ObjectUtils;
 
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;
 
private static final Pattern CONTENT_TYPE_HEADER = Pattern.compile(HttpHeaders.CONTENT_TYPE + ":\\s*([^\r\n]+)", Pattern.CASE_INSENSITIVE);
 
static class StringMultipart extends ArrayList<String> {
}
 
private static StringMultipart readMultipart(HttpInputMessage inputMessage) throws IOException {
    String boundary = inputMessage.getHeaders().getContentType().getParameter("boundary");
    Assert.notNull(boundary, "boundary parameter should be specified");
 
    ArrayList<String> result = new ArrayList<>();
 
    try (InputStream is = inputMessage.getBody(); ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
        MultipartStream multipartStream = new MultipartStream(is, boundary.getBytes(StandardCharsets.US_ASCII));
        multipartStream.setHeaderEncoding(StandardCharsets.US_ASCII.toString());
        boolean nextPart = multipartStream.skipPreamble();
        while (nextPart) {
            String headers = multipartStream.readHeaders();
            Matcher headerMatcher = CONTENT_TYPE_HEADER.matcher(headers);
            Charset bodyCharset = ObjectUtils.defaultIfNull(
                        headerMatcher.find() ? MediaType.parseMediaType(headerMatcher.group(1)).getCharset() : null,
                        StandardCharsets.UTF_8);
 
            multipartStream.readBodyData(baos);
            result.add(baos.toString(bodyCharset.toString()));
            baos.reset();
            nextPart = multipartStream.readBoundary();
        }
    }
 
    return result;
}

Sending/receiving using Apache mime4j:

Apache mime4j + Spring

import org.apache.james.mime4j.dom.Message;
import org.apache.james.mime4j.dom.Multipart;
import org.apache.james.mime4j.field.Fields;
import org.apache.james.mime4j.message.BodyPartBuilder;
import org.apache.james.mime4j.message.DefaultMessageWriter;
import org.apache.james.mime4j.message.MultipartBuilder;
import org.apache.james.mime4j.stream.EntityState;
import org.apache.james.mime4j.stream.Field;
import org.apache.james.mime4j.stream.MimeTokenStream;
 
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.MimeType;
import org.springframework.web.client.RestTemplate;
 
public void requestMultipartApacheMime4jSpring() throws IOException {
    Multipart multipart = MultipartBuilder.create().setSubType("form-data")
                .addBodyPart(BodyPartBuilder.create().setBody("This is a message!", StandardCharsets.UTF_8)
                            .setField(Fields.contentType("text/plain; charset=UTF-8"))
                            .setContentDisposition("form-data", "text-part").build())
                .build();
 
    Message message = Message.Builder.of().setBody(multipart).build();
 
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
 
    new DefaultMessageWriter().writeBody(message.getBody(), bos);
 
    HttpHeaders httpHeaders = new HttpHeaders();
 
    httpHeaders.setContentLength(bos.size());
    httpHeaders.setAccept(Collections.singletonList(MediaType.MULTIPART_FORM_DATA));
 
    for (Field field : message.getHeader()) {
        httpHeaders.add(field.getName(), field.getBody());
    }
 
    System.out.println(httpHeaders.toString());
    System.out.println(new String(bos.toByteArray(), StandardCharsets.UTF_8));
 
    ResponseEntity<byte[]> responseEntity = new RestTemplate().postForEntity(
                "http://host.com/path",
                new HttpEntity<>(bos.toByteArray(), httpHeaders),
                byte[].class);
 
    MimeTokenStream mimeTokenStream = new MimeTokenStream();
    mimeTokenStream.parseHeadless(new ByteArrayInputStream(responseEntity.getBody()),
                responseEntity.getHeaders().getContentType().toString());
 
    do {
        if (mimeTokenStream.getState() == EntityState.T_BODY) {
            System.out.println(IOUtils.toString(mimeTokenStream.getInputStream(),
                        ObjectUtils.defaultIfNull(MimeType
                                    .valueOf(mimeTokenStream.getBodyDescriptor().getMimeType()).getCharset(),
                                    StandardCharsets.UTF_8)));
        }
    } while (mimeTokenStream.next() != EntityState.T_END_OF_STREAM);
}

See also: RFC 2045, RFC 2046.

What channels support non-blocking I/O in Java7?

Pipes and sockets support non-blocking I/O via select() mechanism (implement java.nio.channels.SelectableChannel), and java.nio.channels.AsynchronousFileChannel supports non-blocking I/O using java.util.concurrent.Future interface.

See Why FileChannel in Java is not non-blocking?

How to created and utilize a named pipe?

In Java it is not possible to create a named pipe one can do it by calling Runtime.exec("mkfifo") in Linux or using JNA in Windows. Consuming the existing pipe is done in usual way:
FileInputStream pipeStream = new FileInputStream("\\\\.\\pipe\\my_pipe");
...
pipeStream.close();

How to define a location for temporary directory?

Unfortunately, JVM does not initialize java.io.tmpdir system variable from TMP or TEMP environment variable for any OS except Windows (see Environment variable to control ''java.io.tmpdir''). So to be compatible pass -Djava.io.tmpdir=/work to your JDK.

How to terminate Java application gracefully?

taskkill /t will not terminate Java process started by start /b. And taskkill /f will kill the process without letting shutdown hooks to run.

Listen on socket, pipe or check existence of a file and perform graceful termination programmatically.

How to generate PDF from HTML+CSS?

Where can I get JAI?

As Maven artifacts for JAI are brocken, use alternative / clones:

Where do “interned” string values are stored? Can they be GC'ed?

Each time you call String#intern() the Java allocates the memory on the PermGen space. If you have a very heavy application with tons of classes, the classes are competing with the interned strings on the space. While the GC does clean up the permgen space (at least on Sun JDK), it does it only in a “stop the world” GC and not in a CMS which you typically configure your webapp or desktop to. Bottom line: items in the intern pool can be GC'd, but it's complex and unusual.

What's the semantic difference between org.apache.commons.lang.NotImplementedException and java.lang.UnsupportedOperationException?

Not implemented means “not yet implemented, but presumably will be eventually”. Is typically static and nothing the client can do to change it.
Unsupported means “cannot be implemented because the operation doesn't make sense to support”. Is typically state driven (e.g Bicycle.drive(fish)).

See also Restore NotImplementedException and UnhandledException.

What is the best way to handle ranges of numbers?

Have a look at Range API in Apache Commons Lang and Ranges in Guava Collections (see Ranges in Java, what's the best approach?). If that API is not enough, you need Interval tree implementation (see Data structure for quick interval look up, IntervalTree Java implementation, Interval Tree Java Implementation).

Is there Java library for accessing serial ports?

From Serial Programming/Serial Java:
  • RXTX for Java – native library providing serial and parallel communication
  • JSSC (Java Simple Serial Connector)

See also:

How to access private fields?

Here comes the code that allows to do that:
/**
 * Get the value of private field {@code fieldName} of given object {@code target}.
 */
public static <T> T getPrivateField(Object target, String fieldName) {
    try {
        return getPrivateField(target, target.getClass(), fieldName);
    }
    catch (NoSuchFieldException e) {
        throw new RuntimeException(e);
    }
}
 
/**
 * Get the value of private field {@code fieldName} of given object {@code target} which is treated as class
 * {@code clazz}.
 *
 * @throws NoSuchFieldException
 *             if given field was not found
 */
@SuppressWarnings("unchecked")
private static <T> T getPrivateField(Object target, Class<?> clazz, String fieldName) throws NoSuchFieldException {
    try {
        Field field = clazz.getDeclaredField(fieldName);
        field.setAccessible(true);
        return (T) field.get(target);
    }
    catch (NoSuchFieldException e) {
        if (clazz.getSuperclass() == Object.class) {
            // Field is really not found:
            throw e;
        }
 
        // Try super class:
        return getPrivateField(target, clazz.getSuperclass(), fieldName);
    }
    catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}

The same, but using Spring utility methods:

import org.springframework.util.ReflectionUtils;
 
/**
 * Get the value of private field {@code fieldName} of given object {@code target}.
 */
@SuppressWarnings("unchecked")
public static <T> T getField(Object target, String fieldName) {
    Field field = ReflectionUtils.findField(target.getClass(), fieldName);
    ReflectionUtils.makeAccessible(field);
    return (T) ReflectionUtils.getField(field, target);
}

The same, but using Apache Commons Lang utility methods:

import org.apache.commons.lang3.reflect.FieldUtils;
 
/**
 * Get the value of private field {@code fieldName} of given object {@code target}.
 */
@SuppressWarnings("unchecked")
public static <T> T getField(Object target, String fieldName) {
    try {
        return (T) FieldUtils.readField(target, fieldName, true);
    }
    catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}

Tail recursion is functionally equivalent to iteration. Since Java does not yet support tail call optimization, describe how to transform a simple tail recursive function into a loop and why one is typically preferred over the other.

Here is an example of a typical recursive function, computing the arithmetic series 1, 2, 3…N. Notice how the addition is performed after the function call. For each recursive step, we add another frame to the stack.
public int sumFromOneToN(int n) {
  if (n < 1) {
    return 0;
  }
 
  return n + sumFromOneToN(n - 1);
}

Tail recursion occurs when the recursive call is in the tail position within its enclosing context – after the function calls itself, it performs no additional work. That is, once the base case is complete, the solution is apparent. For example:

public int sumFromOneToN(int n, int a) {
  if (n < 1) {
    return a;
  }
 
  return sumFromOneToN(n - 1, a + n);
}

Here you can see that a plays the role of the accumulator – instead of computing the sum on the way down the stack, we compute it on the way up, effectively making the return trip unnecessary, since it stores no additional state and performs no further computation. Once we hit the base case, the work is done – below is that same function, “unrolled”.

public int sumFromOneToN(int n) {
  int a = 0;
 
  while(n > 0) {
    a += n--;
  }
 
  return a;
}

Another example of not tail recursion (classical):

int factorial(int n) {
    return (n == 0) ? 1 : n * factorial(n - 1);
}
int fac_times(int n, int acc) {
    return (n == 0) ? acc : fac_times(n - 1, acc * n);
}
int factorial(int n) {
    return fac_times(n, 1);
}

Many functional languages natively support tail call optimization, however JVM does not. In order to implement recursive functions in Java, we need to be aware of this limitation to avoid StackOverflowErrors. In Java, iteration is almost universally preferred to recursion.

programming/java/start.txt · Last modified: 2016/03/23 17:01 by dmitry
 
 
Recent changes RSS feed Driven by DokuWiki