Skip to content

Thread: make the thread-local map on first use - #65

Open
duncanmcqueen wants to merge 1 commit into
ingelabs:masterfrom
duncanmcqueen:fix-thread-locals
Open

duncanmcqueen wants to merge 1 commit into
ingelabs:masterfrom
duncanmcqueen:fix-thread-locals

Conversation

@duncanmcqueen

Copy link
Copy Markdown
Contributor

Split from #59.

Problem and fix

ThreadLocal uses Thread.locals, which a Thread constructor sets. Kaffe makes the Thread object of the main thread without a constructor: KaffeVM_attachFakedThreadInstance() in kaffe/kaffevm/thread.c calls newObject(ThreadClass) and sets the fields from C. It does not set locals. Thus each ThreadLocal on the main thread throws NullPointerException. Kaffe uses the same function for native threads that attach through JNI.

Classpath itself uses ThreadLocal during startup (VMAccessController), so Kaffe cannot start any program.

This change makes locals non-final, and Thread.getThreadLocals() makes the map when locals is null.

How to reproduce

This problem occurs only on a VM that makes Thread objects without a constructor. JamVM does not, so the test passes on JamVM with and without this change.

javac MainThreadLocal.java
kaffe MainThreadLocal
MainThreadLocal.java
/**
 * A ThreadLocal must work on the main thread. On Kaffe 1.1.x the main
 * Thread object is made without running a Thread constructor, so
 * Thread.locals is null.
 */
public class MainThreadLocal
{
  public static void main(String[] args)
  {
    try
      {
        ThreadLocal<String> t = new ThreadLocal<String>();
        t.set("value");
        boolean ok = "value".equals(t.get());
        System.out.println((ok ? "PASS" : "FAIL") + ": get() = " + t.get());
        System.exit(ok ? 0 : 1);
      }
    catch (Throwable e)
      {
        System.out.println("FAIL: " + e);
        e.printStackTrace(System.out);
        System.exit(1);
      }
  }
}

Results

Linux x86_64, ingelabs/classpath master (0406074), JamVM master, javac from JDK 8, autoconf 2.73, automake 1.19, the configure options of the CI Linux job, out-of-tree build. "Before" is master. "After" is master with this commit.

On Kaffe 1.1.10-pre, the last version in its repository (Haiku x86_64), with the Thread classes of master before glibj.zip, Kaffe stops before main():

Internal error: caught an unexpected exception.
Please check your CLASSPATH and your installation.
java/lang/ExceptionInInitializerError
   at java.lang.ClassLoader.getSystemClassLoader (ClassLoader.java:799)
caused by java/lang/NullPointerException:
   at java.lang.ThreadLocal.get (ThreadLocal.java:147)
   at java.security.VMAccessController.pushContext (VMAccessController.java:108)
   at java.security.AccessController.doPrivileged (AccessController.java:93)
   at gnu.java.nio.charset.Provider.provider (Provider.java:262)
   at java.nio.charset.Charset.provider (Charset.java:253)
   at java.nio.charset.Charset.charsetForName (Charset.java:208)
   at java.nio.charset.Charset.forName (Charset.java:188)
   at java.util.zip.ZipFile$PartialInputStream.<clinit> (ZipFile.java:528)
   ...

With this change: PASS: get() = value.

On JamVM (Linux): PASS: get() = value before and after.

Platforms

Not specific to Haiku, but specific to the VM. The problem occurs with Kaffe on all systems. Kaffe's repository is archived, so I cannot fix it in Kaffe.

I understand if you prefer not to have a workaround for one VM in Thread. The change is small, and it has no effect on VMs that run a Thread constructor.

AI assistance

An AI model (Claude Code, by Anthropic) wrote this change, the test and this text. The repository owner directed the work and checked the results. Please review it as you review other contributions.

🤖 Generated with Claude Code

Some VMs (for example Kaffe) make the Thread object of the main
thread without running a constructor, so its locals field is null and
every ThreadLocal fails. Make the field non-final and create the map
in getThreadLocals() when it is null.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: duncanmcqueen <dwmcqueen@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant