1

I'm wondering whether before start() method is called, instances of Thread are merely a standard Java objects or if some special JVM/OS level resources are allocated right from the moment they are created (like for example pre-allocated memory for their stack etc). Based on a preliminary research, they seem like ordinary objects, but it would be awesome if some JVM experts could confirm this.

I'm mostly concerned regarding previously mentioned thread's stack memory, as the JVM spec states "Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread". I wonder if "created" here refers to a call to start() method or a Thread instance being constructed (I'm honestly not up2date with the exact relation between OS threads, JVM threads and Thread objects, hence my confusion. Also I think I might have heard it changed a bit during last few years, but I can't recall exactly). Furthermore, I'm guessing, that even in the case some OS virtual memory is allocated at the moment a Thread instance is constructed, actual physical memory pages for its stack will be allocated only after the thread starts to use, which, I guess again, is only after it is start()-ed.

This is the "change I might have heard about": jep-425 introduced in java-19. It changes the mapping between OS threads and JVM threads to M:N. I'm however still not sure about the mapping between Thread objects and JVM threads (I'm almost sure that mapping between start()-ed Thread objects and JVM threads is 1:1, but not sure if a JVM thread is created on Thread instance creation or on start(). I've asked another question regarding this)

Gimby
  • 5,095
  • 2
  • 35
  • 47
morgwai
  • 2,513
  • 4
  • 25
  • 31
  • 1
    Why would you be creating a lot of Thread objects without starting them? That doesn't make sense, unless you're making the classic mistake of extending `Thread` instead of implementing `Runnable`. – Mark Rotteveel Jul 20 '23 at 10:08
  • Sounds like you need a scalable thread pool – MadProgrammer Jul 20 '23 at 10:10
  • @MarkRotteveel it's due to an API that is beyond my control. I do totally agree that this sucks, but that's what I have to deal with... :( – morgwai Jul 20 '23 at 10:20
  • @MarkRotteveel only if I can prove to my client that this will scale much worse (for example due to such special JVM/OS resources being pre-allocated), then **MAYBE** they will consider changing it, hence this question (but I'm afraid they will actually say "don't worry, we will buy more server resources", because it will be easier for them due to their corporate politics...) – morgwai Jul 20 '23 at 10:30

1 Answers1

3

Although the Thread constructor does quite some checks and initialization, it will not bind the Thread instance to a native OS thread. That will only happen on Thread.start(), so in that sense an unstarted Thread is not a "heavy" object (by which I mean, it doesn't have a native peer).

Probably the most expensive part is if the Thread is constructed with inheritThreadLocals set to true (which happens in a lot of the usual constructors of Thread), and the creating thread has a lot of thread local values in its map.

That said, and reiterating the point of my comment on the question, creating a lot of threads without starting them is unusual, and generally indicates you're doing something wrong (e.g. extending Thread instead of implementing Runnable), you may want to look for alternatives.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • how about JVM-thread's stack memory? I'm concerned due to [this part of JVM spec](https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.5.2) Please see my update to the question for details. Many thanks!! :) – morgwai Jul 20 '23 at 11:24
  • 2
    @morgwai - the stack is allocated when the `Thread` is started, and discarded when the thread terminates. – Stephen C Jul 20 '23 at 13:17
  • @StephenC thanks for the answer :) is it stated somewhere in the JVM spec/javadocs or is it just a common (sole?) implementation? I was trying to find some source regarding this, but no luck :( Thanks again! – morgwai Jul 20 '23 at 13:54
  • 2
    It is not stated in the specifications. This is just how (all) HotSpot JVMs work. The OpenJDK source code is the ultimate source for this information. So that means that *in theory* a JVM *could* manage the stack in some other way. But I'm not aware of any existing JVM implementation that does that. – Stephen C Jul 20 '23 at 14:52
  • Btw. even then, thread stacks are usually allocated lazily, so in most cases, the won't occupy as much space either - see https://stackoverflow.com/questions/53451103/java-using-much-more-memory-than-heap-size-or-size-correctly-docker-memory-limi/53624438#53624438 and https://github.com/apangin/jstackmem/blob/master/jstackmem.py – Juraj Martinka Jul 24 '23 at 05:40