Java: Can a child thread outlive the main thread

I came to know in Java that: children threads won’t outlive the main thread, but, seemingly, the behavior of this application shows different results.

The child thread keeps working while the main one has done working!

Here is what I do:

public class Main {

public static void main(String[] args) {

    Thread t = Thread.currentThread();

    // Starting a new child thread here
    new NewThread();

    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    System.out.println("\n This is the last thing in the main Thread!");


    }
}

class NewThread implements Runnable {

private Thread t;

NewThread(){
    t= new Thread(this,"My New Thread");
    t.start();
}

public void run(){
    for (int i = 0; i <40; i++) {
        try {
            Thread.sleep(4000);
            System.out.printf("Second thread printout!\n");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

}

What do I fail to understand here … Or that’s a new feature in Java starting from JDK 9?

Solution:

According to the documentation of Thread#setDaemon:

The Java Virtual Machine exits when the only threads running are all daemon threads.

Your child thread is not a daemon thread, so the JVM does not exit even though the main thread no longer runs. If you call t.setDaemon(true); in the constructor of NewThread, then the JVM will exit after the main thread has finished executing.

Securely Export Packages to Java Modules

I was answering this question, where I recommended utilizing exports to syntax to prevent external consumers from accessing code that is intended for internal use between modules.

But on further reflection, the only real safety checking that modules implement is that it matches the name. Consider this example where I am implementing two modules:

module com.my.a {
    exports com.my.unsafe to com.my.b
}

module com.my.b {
    requires com.my.a
}

The package com.my.unsafe contains code that would be unsafe to have exposed. Is there any way to securely export this to internal modules without exposing them externally?

In the above example, a rogue entity could simply name their module com.my.b and would gain access to the code (not secure). The JLS doesn’t seem to spell out anything that can prevent it.

Solution:

The hashing of modules as pointed by Alan shall work in your case. Though I personally like the description and the example from the JMOD tool which directly answers your question :

With the --hash-modules option or the jmod hash command, you can, in
each module’s descriptor, record hashes of the content of the modules
that are allowed to depend upon it, thus “tying” together these
modules.

This lets you to allow a package to be exported to one or
more specifically-named modules and to no others through qualified
exports
. The runtime verifies if the recorded hash of a module matches
the one resolved at run time; if not, the runtime returns an error.

Java 8/9: Can a character in a String be mapped to its indices (using streams)?

Given a String s and a char c, I’m curious if there exists some method of producing a List<Integer> list from s (where the elements within list represent the indices of c within s).

A close, but incorrect approach would be:

public static List<Integer> getIndexList(String s, char c) {
    return s.chars()
            .mapToObj(i -> (char) i)
            .filter(ch -> ch == c)
            .map(s::indexOf) // Will obviously return the first index every time.
            .collect(Collectors.toList());
}

The following inputs should yield the following output:

getIndexList("Hello world!", 'l') -> [2, 3, 9]

Solution:

Can be done with IntStream

public static List<Integer> getIndexList(String s, char c) {
    return IntStream.range(0, s.length())
                    .filter(index -> s.charAt(index) == c)
                    .boxed()
                    .collect(Collectors.toList());
}

In Java9, finalizers have been deprecated, instead cleaners have been introduced. What is the difference between the two?

In Java9 cleaners have been introduced and finalizers have been deprecated.
What is the purpose of introducing the cleaners and how and in what particular scenario we should be using them and not finalizers?

Solution:

The Deprecation of Finalizer in registers state the reason for the decision :-

Finalizers are inherently problematic and their use can lead to performance issues, deadlocks, hangs, and other problematic behavior.

Furthermore, the timing of finalization is unpredictable with no guarantee that a finalizer will be called. Classes whose instances hold non-heap resources should provide a method to enable explicit release of those resources, and they should also implement java.lang.AutoCloseable if appropriate.

The proposed solution as an alternative to using the Finalizers were the introduced Cleaners which would provide easy registration and cancellation of cleanup functions for objects.

The Cleaner
and PhantomReference provide more flexible and efficient ways to release resources when an object becomes unreachable.

Applications create a cleanup service for their own use and the service terminates when it is no longer in use.

Use: Once an object has become Phantom reachable the cleanup actions performed on the same are registered and managed by a Cleaner. Registering an object reference and corresponding cleaning action returns a Cleanable. The most efficient use is to explicitly invoke the clean method when the object is closed or no longer needed.

Note: Prior to Java9, a similar implementation of a Cleaner has been residing under sun.misc package as well.

How is Java 9 running code compiled with Java 8 that is using a non-exported package

I compiled following code using Java-8 compiler:

package pack;
import sun.util.calendar.CalendarUtils;
public class A {
    public static void main(String[] args) {
        System.out.println(CalendarUtils.isGregorianLeapYear(2018));
    }
}

I compiled the above code using Java-8 compiler as:

gyan@gyan-pc:~/codes/java$ ~/Documents/softwares/Linux/jdk1.8.0_131/bin/javac -d . a.java
a.java:2: warning: CalendarUtils is internal proprietary API and may be removed in a future release
import sun.util.calendar.CalendarUtils;
                        ^
a.java:9: warning: CalendarUtils is internal proprietary API and may be removed in a future release
        System.out.println(CalendarUtils.isGregorianLeapYear(2018));
                           ^
2 warnings

Version of my default Java Interpreter:

gyan@gyan-pc:~/codes/java$ java -version
java version "9.0.1"
Java(TM) SE Runtime Environment (build 9.0.1+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.1+11, mixed mode)

And I can run the compiled code using Java-9 interpreter without any error.

gyan@gyan-pc:~/codes/java$ java pack.a
false

According to my knowledge: At runtime the package “pack” will be contained inside a special module called “Unnamed module”. The “Unnamed module” requires all the modules from Java platform module. But only that package can be used by the “Unnamed module” which are exported by the corresponding module.

My question is:
Here the module java.base is not exporting the package “sun.util.calendar”. Then how the “Unnamed module” is using it?

Solution:

As pointed by Alan, the section Relaxed strong encapsulation states the following in this respect :-

--illegal-access=permit opens each package in each module in the run-time image to code in all unnamed modules, i.e., to code on the
class path, if that package existed in JDK 8. This enables both static
access, i.e., by compiled bytecode, and deep reflective access, via
the platform’s various reflection APIs.

The first reflective-access operation to any such package causes a
warning to be issued, but no warnings are issued after that point.
This single warning describes how to enable further warnings. This
warning cannot be suppressed.

This mode is the default in JDK 9. It will be phased out in a future
release and, eventually, removed.

Also, if you try to execute the compiled code with

.../jdk-9.0.1.jdk/Contents/Home/bin/java --illegal-access=deny pack.Some

using the future default flag, you wouldn’t be able to execute the code as expected with the following trace :

Exception in thread "main" java.lang.IllegalAccessError: class
pack.Some (in unnamed module @0x1055e4af) cannot access class
sun.util.calendar.CalendarUtils (in module java.base) because module
java.base does not export sun.util.calendar to unnamed module
@0x1055e4af    at pack.Some.main(Some.java:7)

JAVA ERROR : package com.sun.rowset is not visible : com.sun.rowset is declared in module java.sql.rowset, which does not export it

I’m simply try to run this code:

import com.sun.rowset.CachedRowSetImpl;

public class Test {
    public static void main(String[] args) throws Exception{
        CachedRowSetImpl crs = new CachedRowSetImpl();
    }
}

When I run it I get:

Error:(1, 15) java: package com.sun.rowset is not visible (package
com.sun.rowset is declared in module java.sql.rowset, which does not
export it)

I’m using IntelliJ and I tried to import rs2xml.jar, and that still doesnt help.

Solution:

With Java 9 you can not access this class anymore. And in the ideal way you shouldn’t do that. That is because this class’s package is not exported in the module javax.sql.rowset. The proper way to do that in Java-9 will be:

import javax.sql.rowset.*; 

public class Test {
    public static void main(String[] args) throws Exception {

        CachedRowSet crs = RowSetProvider.newFactory().createCachedRowSet();
    }
}

To understand that we can go to the module description (module-info.java) and find a list of exported packages:

exports javax.sql.rowset;
exports javax.sql.rowset.serial;
exports javax.sql.rowset.spi;

takeWhile() working differently with flatmap

I am creating snippets with takeWhile to explore its possibilities. When used in conjunction with flatMap, the behaviour is not in line with the expectation. Please find the code snippet below.

String[][] strArray = {{"Sample1", "Sample2"}, {"Sample3", "Sample4", "Sample5"}};

Arrays.stream(strArray)
        .flatMap(indStream -> Arrays.stream(indStream))
        .takeWhile(ele -> !ele.equalsIgnoreCase("Sample4"))
        .forEach(ele -> System.out.println(ele));

Actual Output:

Sample1
Sample2
Sample3
Sample5

ExpectedOutput:

Sample1
Sample2
Sample3

Reason for the expectation is that takeWhile should be executing till the time the condition inside turns true. I have also added printout statements inside flatmap for debugging. The streams are returned just twice which is inline with the expectation.

However, this works just fine without flatmap in the chain.

String[] strArraySingle = {"Sample3", "Sample4", "Sample5"};
Arrays.stream(strArraySingle)
        .takeWhile(ele -> !ele.equalsIgnoreCase("Sample4"))
        .forEach(ele -> System.out.println(ele));

Actual Output:

Sample3

Here the actual output matches with the expected output.

Disclaimer: These snippets are just for code practise and does not serve any valid usecases.

Solution:

If the stream is ordered, takeWhile should show the expected behavior. This is not entirely the case in your code because you use forEach, which waives order. If you care about it, which you do in this example, you should use forEachOrdered instead. Funny thing: That doesn’t change anything. 🤔

So maybe the stream isn’t ordered in the first place? (In that case the behavior is ok.) If you create a temporary variable for the stream created from strArray and check whether it is ordered by executing the expression ((StatefulOp) stream).isOrdered(); at the breakpoint, you will find that it is indeed ordered:

String[][] strArray = {{"Sample1", "Sample2"}, {"Sample3", "Sample4", "Sample5"}};

Stream<String> stream = Arrays.stream(strArray)
        .flatMap(indStream -> Arrays.stream(indStream))
        .takeWhile(ele -> !ele.equalsIgnoreCase("Sample4"));

// breakpoint here
System.out.println(stream);

That means that this is very likely an implementation error.

Into The Code

As others have suspected, I now also think that this might be connected to flatMap being eager. More precisely, both problems might have the same root cause.

Looking into the source of WhileOps, we can see these methods:

@Override
public void accept(T t) {
    if (take = predicate.test(t)) {
        downstream.accept(t);
    }
}

@Override
public boolean cancellationRequested() {
    return !take || downstream.cancellationRequested();
}

This code is used by takeWhile to check for a given stream element t whether the predicate is fulfilled:

  • If so, it passes the element on to the downstream operation, in this case System.out::println.
  • If not, it sets take to false, so when it is asked next time whether the pipeline should be canceled (i.e. it is done), it returns true.

This covers the takeWhile operation. The other thing you need to know is that forEachOrdered leads to the terminal operation executing the method ReferencePipeline::forEachWithCancel:

@Override
final boolean forEachWithCancel(Spliterator<P_OUT> spliterator, Sink<P_OUT> sink) {
    boolean cancelled;
    do { } while (
            !(cancelled = sink.cancellationRequested())
            && spliterator.tryAdvance(sink));
    return cancelled;
}

All this does is:

  1. check whether pipeline was canceled
  2. if not, advance the sink by one element
  3. stop if this was the last element

Looks promising, right?

Without flatMap

In the “good case” (without flatMap; your second example) forEachWithCancel directly operates on the WhileOp as sink and you can see how this plays out:

  • ReferencePipeline::forEachWithCancel does its loop:
    • WhileOps::accept is given each stream element
    • WhileOps::cancellationRequested is queried after each element
  • at some point "Sample4" fails the predicate and the stream is canceled

Yay!

With flatMap

In the “bad case” (with flatMap; your first example), forEachWithCancel operates on the flatMap operation, though, , which simply calls forEachRemaining on the ArraySpliterator for {"Sample3", "Sample4", "Sample5"}, which does this:

if ((a = array).length >= (hi = fence) &&
    (i = index) >= 0 && i < (index = hi)) {
    do { action.accept((T)a[i]); } while (++i < hi);
}

Ignoring all that hi and fence stuff, which is only used if the array processing is split for a parallel stream, this is a simple for loop, which passes each element to the takeWhile operation, but never checks whether it is cancelled. It will hence eagerly ply through all elements in that “substream” before stopping, likely even through the rest of the stream.

In Summary

I think this is a bug.

Why does \R behave differently in regular expressions between Java 8 and Java 9?

The following code compiles in both Java 8 & 9, but behaves differently.

class Simple {
    static String sample = "\nEn un lugar\r\nde la Mancha\nde cuyo nombre\r\nno quiero acordame";

    public static void main(String args[]){
        String[] chunks = sample.split("\\R\\R");
        for (String chunk: chunks) {
            System.out.println("Chunk : "+chunk);
        }
    }
}

When I run it with Java 8 it returns:

Chunk : 
En un lugar
de la Mancha
de cuyo nombre
no quiero acordame

But when I run it with Java 9 the output is different:

Chunk : 
En un lugar
Chunk : de la Mancha
de cuyo nombre
Chunk : no quiero acordame

Why?

Solution:

It was a bug in Java 8 and it got fixed: JDK-8176029 : “Linebreak matcher is not equivalent to the pattern as stated in javadoc”.

Also see: Java-8 regex negative lookbehind with `\R`