Java
made by https://0x3d.site
GitHub - code-review-checklists/java-concurrency: Checklist for code reviewsChecklist for code reviews. Contribute to code-review-checklists/java-concurrency development by creating an account on GitHub.
Visit Site
GitHub - code-review-checklists/java-concurrency: Checklist for code reviews
Code Review Checklist: Java Concurrency
Design
- Concurrency is rationalized?
- Can use patterns to simplify concurrency?
- Immutability/Snapshotting
- Divide and conquer
- Producer-consumer
- Instance confinement
- Thread/Task/Serial thread confinement
- Active object
- Code smells, identifying that a class or a subsystem could potentially be redesigned for better:
Documentation
- Thread safety is justified in comments?
- Class (method, field) has concurrent access documentation?
- Threading model of a subsystem (class) is described?
- Concurrent control flow (or data flow) of a subsystem (class) is described?
- Class is documented as immutable, thread-safe, or not thread-safe?
- Used concurrency patterns are pronounced?
ConcurrentHashMap
is not stored in a variable ofMap
type?compute()
-like methods are not called on a variable ofConcurrentMap
type?@GuardedBy
annotation is used?- Safety of a benign race (e. g. unbalanced synchronization) is explained?
- Each use of
volatile
is justified? - Each field that is neither
volatile
nor annotated with@GuardedBy
has a comment?
Insufficient synchronization
- Static methods and fields are thread-safe?
- Thread doesn't wait in a loop for a non-volatile field to be updated by another thread?
- Read access to a non-volatile, concurrently updatable primitive field is protected?
- Servlets, Controllers, Filters, Handlers,
@Get
/@Post
methods are thread-safe? - Calls to
DateFormat.parse()
andformat()
are synchronized?
Excessive thread safety
- No "extra" (pseudo) thread safety?
- No atomics on which only
get()
andset()
are called? - Class (method) needs to be thread-safe?
ReentrantLock
(ReentrantReadWriteLock
,Semaphore
) needs to be fair?
Race conditions
- No
put()
orremove()
calls on aConcurrentMap
(or Cache) afterget()
orcontainsKey()
? - No point accesses to a non-thread-safe collection outside of critical sections?
- Iteration over a non-thread-safe collection doesn't leak outside of a critical section?
- A non-thread-safe collection is not returned wrapped in
Collections.unmodifiable*()
from a getter in a thread-safe class? - A synchronized collection is not returned from a getter? in a thread-safe class?
- Non-trivial mutable object is not returned from a getter in a thread-safe class?
- No separate getters to an atomically updated state?
- No check-then-act race conditions (state used inside a critical section is read outside of it)?
coll.toArray(new E[coll.size()])
is not called on a synchronized collection?- No race conditions with user or programmatic input or interop between programs?
- No check-then-act race conditions with file system operations?
- No concurrent
invalidate(key)
andget()
calls on Guava's loadingCache
? Cache.put()
is not used (nor exposed in the own Cache interface)?- Concurrent invalidation race is not possible on a lazily initialized state?
- Iteration, Stream pipeline, or copying a
Collections.synchronized*()
collection is protected by the lock? - A synchronized collection is passed into
containsAll()
,addAll()
,removeAll()
, orputAll()
under the lock?
Testing
- Considered adding multi-threaded unit tests for a thread-safe class or method?
- What is the worst thing that might happen if the code has a concurrency bug?
- A shared
Random
instance is not used from concurrent test workers? - Concurrent test workers coordinate their start?
- There are more test threads than CPUs (if possible for the test)?
- Assertions in parallel threads and asynchronous code are handled properly?
- Checked the result of
CountDownLatch.await()
?
Locks
- Can use some concurrency utility instead of a lock with conditional
wait
(await
) calls? - Can use Guava’s
Monitor
instead of a lock with conditionalwait
(await
) calls? - Can use
synchronized
instead of aReentrantLock
? lock()
is called outside oftry {}
? No statements betweenlock()
andtry {}
?
Avoiding deadlocks
- Can avoid nested critical sections?
- Locking order for nested critical sections is documented?
- Dynamically determined locks for nested critical sections are ordered?
- No extension API calls within critical sections?
- No calls to
ConcurrentHashMap
's methods (incl.get()
) incompute()
-like lambdas on the same map?
Improving scalability
- Critical section is as small as possible?
- Can use
ConcurrentHashMap.compute()
or Guava'sStriped
for per-key locking? - Can replace a blocking collection or a queue with a concurrent one?
- Can use
ClassValue
instead ofConcurrentHashMap<Class, ...>
? - Considered
ReadWriteLock
(orStampedLock
) instead of a simple lock? StampedLock
is used instead ofReadWriteLock
when reentrancy is not needed?- Considered
LongAdder
instead of anAtomicLong
for a "hot field"? - Considered queues from JCTools instead of the standard concurrent queues?
- Considered Caffeine cache instead of other caching libraries?
- Can apply speculation (optimistic concurrency) technique?
- Considered
ForkJoinPool
instead ofnewFixedThreadPool(N)
?
Lazy initialization and double-checked locking
- Lazy initialization of a field should be thread-safe?
- Considered double-checked locking for a lazy initialization to improve performance?
- Double-checked locking follows the SafeLocalDCL pattern?
- Considered eager initialization instead of a lazy initialization to simplify code?
- Can do lazy initialization with a benign race and without locking to improve performance?
- Holder class idiom is used for lazy static fields rather than double-checked locking?
Non-blocking and partially blocking code
- Non-blocking code has enough comments to make line-by-line checking as easy as possible?
- Can use immutable POJO + compare-and-swap operations to simplify non-blocking code?
- Boundaries of non-blocking or benignly racy code are identified with WARNING comments?
- Busy waiting (spin loop), all calls to
Thread.yield()
andThread.onSpinWait()
are justified?
Threads and Executors
- Thread is named?
- Can use
ExecutorService
instead of creating a newThread
each time some method is called? - ExecutorServices are not created within short-lived objects (but rather reused)?
- No network I/O in a CachedThreadPool?
- No blocking (incl. I/O) operations in a
ForkJoinPool
or in a parallel Stream pipeline? - Can execute non-blocking computation in
FJP.commonPool()
instead of a custom thread pool? ExecutorService
is shut down explicitly?- Callback is attached to a
CompletableFuture
(SettableFuture
) in non-async mode only if either:- the callback is lightweight and non-blocking; or
- the future is completed and the callback is attached from the same thread pool?
- Adding a callback to a
CompletableFuture
(SettableFuture
) in non-async mode is justified? - Actions are delayed via a
ScheduledExecutorService
rather thanThread.sleep()
? - Checked the result of
awaitTermination()
? ExecutorService
is not assigned into a variable ofExecutor
type?ScheduledExecutorService
is not assigned into a variable ofExecutorService
type?
Parallel Streams
- Parallel Stream computation takes more than 100us in total?
- Comment before a parallel Streams pipeline explains how it takes more than 100us in total?
Futures
- Non-blocking computation needs to be decorated as a
Future
? - Method returning a
Future
doesn't block? - In a method returning a
Future
, considered wrapping an "expected" exception as a failedFuture
?
Thread interruption and Future
cancellation
- Interruption status is restored before wrapping
InterruptedException
with another exception? InterruptedException
is swallowed only in the following kinds of methods:Runnable.run()
,Callable.call()
, or methods to be passed to executors as lambda tasks; or- Methods with "try" or "best effort" semantics?
InterruptedException
swallowing is documented for a method?- Can use Guava's
Uninterruptibles
to avoidInterruptedException
swallowing? Future
is canceled upon catching anInterruptedException
or aTimeoutException
onget()
?
Time
nanoTime()
values are compared in an overflow-aware manner?currentTimeMillis()
is not used to measure time intervals and timeouts?- Units for a time variable are identified in the variable's name or via
TimeUnit
? - Negative timeouts and delays are treated as zeros?
- Tasks connected to system time or UTC time are not scheduled using
ScheduledThreadPoolExecutor
? - Human and external interactions on consumer devices are not scheduled using
ScheduledThreadPoolExecutor
?
ThreadLocal
ThreadLocal
can bestatic final
?- Can redesign a subsystem to avoid usage of
ThreadLocal
(esp. non-static one)? ThreadLocal
is not used just to avoid moderate amount of allocation?- Considered replacing a non-static
ThreadLocal
with an instance-confinedMap<Thread, ...>
?
Thread safety of Cleaners and native code
close()
is concurrently idempotent in a class with aCleaner
orfinalize()
?- Method accessing native state calls
reachabilityFence()
in a class with aCleaner
orfinalize()
? Cleaner
orfinalize()
is used for real cleanup, not mere reporting?- Considered making a class with native state thread-safe?
Design
# Dn.1. If the patch introduces a new subsystem (class, method) with concurrent code, is the necessity for concurrency or thread safety rationalized in the patch description? Is there a discussion of alternative design approaches that could simplify the concurrency model of the code (see the next item)?
A way to nudge thinking about concurrency design is demanding the usage of concurrency tools and language constructs to be justified in comments.
See also an item about unneeded thread-safety of classes and methods.
# Dn.2. Is it possible to apply one or several design patterns (some of them are listed below) to significantly simplify the concurrency model of the code, while not considerably compromising other quality aspects, such as overall simplicity, efficiency, testability, extensibility, etc?
Immutability/Snapshotting. When some state should be updated, a new immutable object (or a
snapshot within a mutable object) is created, published and used, while some concurrent threads may
still use older copies or snapshots. See [EJ Item 17], [JCIP 3.4], RC.5 and
NB.2, CopyOnWriteArrayList
, CopyOnWriteArraySet
, persistent data
structures.
Divide and conquer. Work is split into several parts that are processed independently, each part
in a single thread. Then the results of processing are combined. Parallel
Streams or ForkJoinPool
(see TE.4 and
TE.5) can be used to apply this pattern.
Producer-consumer. Pieces of work are transmitted between worker threads via queues. See [JCIP 5.3], Dl.1, CSP, SEDA.
Instance confinement. Objects of some root type encapsulate some complex hierarchical child state. Root objects are solitarily responsible for the safety of accesses and modifications to the child state from multiple threads. In other words, composed objects are synchronized rather than synchronized objects are composed. See [JCIP 4.2, 10.1.3, 10.1.4]. RC.3, RC.4, and RC.5 describe race conditions that could happen to instance-confined state. TL.4 touches on instance confinement of thread-local state.
Thread/Task/Serial thread confinement. Some state is made local to a thread using top-down
pass-through parameters or ThreadLocal
. See [JCIP 3.3] and the checklist section about
ThreadLocals. Task confinement is a variation of the
idea of thread confinement that is used in conjunction with the divide-and-conquer pattern. It
usually comes in the form of lambda-captured "context" parameters or fields in the per-thread task
objects. Serial thread confinement is an extension of the idea of thread confinement for the
producer-consumer pattern, see [JCIP 5.3.2].
Active object. An object manages its own ExecutorService
or Thread
to do the work. See the
article on Wikipedia and TE.6.
Documentation
# Dc.1. For every class, method, and field that has signs of being thread-safe,
such as the synchronized
keyword, volatile
modifiers on fields, use of any classes from
java.util.concurrent.*
, or third-party concurrency primitives, or concurrent collections: do their
Javadoc comments include
-
The justification for thread safety: is it explained why a particular class, method or field has to be thread-safe?
-
Concurrent access documentation: is it enumerated from what methods and in contexts of what threads (executors, thread pools) each specific method of a thread-safe class is called?
Wherever some logic is parallelized or the execution is delegated to another thread, are there comments explaining why it’s worse or inappropriate to execute the logic sequentially or in the same thread? See PS.1 regarding this.
See also NB.3 and NB.4 regarding justification of non-blocking code, racy code, and busy waiting.
If the usage of concurrency tools is not justified, there is a possibility of code ending up with
unnecessary thread-safety, redundant atomics,
redundant volatile
modifiers, or unneeded Futures.
# Dc.2. If the patch introduces a new subsystem that uses threads or thread
pools, are there high-level descriptions of the threading model, the concurrent control flow (or
the data flow) of the subsystem somewhere, e. g. in the Javadoc comment for the package in
package-info.java
or for the main class of the subsystem? Are these descriptions kept up-to-date
when new threads or thread pools are added or some old ones deleted from the system?
Description of the threading model includes the enumeration of threads and thread pools created and
managed in the subsystem, and external pools used in the subsystem (such as
ForkJoinPool.commonPool()
), their sizes and other important characteristics such as thread
priorities, and the lifecycle of the managed threads and thread pools.
A high-level description of concurrent control flow should be an overview and tie together concurrent control flow documentation for individual classes, see the previous item. If the producer-consumer pattern is used, the concurrent control flow is trivial and the data flow should be documented instead.
Describing threading models and control/data flow greatly improves the maintainability of the system, because in the absence of descriptions or diagrams developers spend a lot of time and effort to create and refresh these models in their minds. Putting the models down also helps to discover bottlenecks and the ways to simplify the design (see Dn.2).
# Dc.3. For classes and methods that are parts of the public API or the extensions API of the project: is it specified in their Javadoc comments whether they are (or in case of interfaces and abstract classes designed for subclassing in extensions, should they be implemented as) immutable, thread-safe, or not thread-safe? For classes and methods that are (or should be implemented as) thread-safe, is it documented precisely with what other methods (or themselves) they may be called concurrently from multiple threads? See also [EJ Item 82], [JCIP 4.5], CON52-J.
If the @com.google.errorprone.annotations.Immutable
annotation is used to mark immutable classes,
Error Prone static analysis tool is capable to detect when a class is
not actually immutable (see a relevant bug
pattern).
# Dc.4. For subsystems, classes, methods, and fields that use some concurrency design patterns, either high-level, such as those mentioned in Dn.2, or low-level, such as double-checked locking or spin looping: are the used concurrency patterns pronounced in the design or implementation comments for the respective subsystems, classes, methods, and fields? This helps readers to make sense out of the code quicker.
Pronouncing the used patterns in comments may be replaced with more succinct documentation
annotations, such as @Immutable
(Dc.3), @GuardedBy
(Dc.7), @LazyInit
(LI.5), or annotations that you define
yourself for specific patterns which appear many times in your project.
# Dc.5. Are ConcurrentHashMap
and ConcurrentSkipListMap
objects stored
in fields and variables of ConcurrentHashMap
or ConcurrentSkipListMap
or ConcurrentMap
type, but not just Map
?
This is important, because in code like the following:
ConcurrentMap<String, Entity> entities = getEntities();
if (!entities.containsKey(key)) {
entities.put(key, entity);
} else {
...
}
It should be pretty obvious that there might be a race condition because an entity may be put into
the map by a concurrent thread between the calls to containsKey()
and put()
(see
RC.1 about this type of race conditions). While if the type of the entities variable
was just Map<String, Entity>
it would be less obvious and readers might think this is only
slightly suboptimal code and pass by.
It’s possible to turn this advice into an inspection in IntelliJ IDEA.
# Dc.6. An extension of the previous item: are ConcurrentHashMaps on which compute()
,
computeIfAbsent()
, computeIfPresent()
, or merge()
methods are called stored in fields and
variables of ConcurrentHashMap
type rather than ConcurrentMap
? This is because
ConcurrentHashMap
(unlike the generic ConcurrentMap
interface) guarantees that the lambdas
passed into compute()
-like methods are performed atomically per key, and the thread safety of the
class may depend on that guarantee.
This advice may seem to be overly pedantic, but if used in conjunction with a static analysis rule
that prohibits calling compute()
-like methods on ConcurrentMap
-typed objects that are not
ConcurrentHashMaps (it’s possible to create such inspection in IntelliJ IDEA too) it could prevent
some bugs: e. g. calling compute()
on a ConcurrentSkipListMap
might be a race condition and
it’s easy to overlook that for somebody who is used to rely on the strong semantics of compute()
in ConcurrentHashMap
.
# Dc.7. Is @GuardedBy
annotation used? If accesses to some fields should be
protected by some lock, are those fields annotated with @GuardedBy
? Are private methods that are
called from within critical sections in other methods annotated with @GuardedBy
? If the project
doesn’t depend on any library containing this annotation (it’s provided by jcip-annotations
, error_prone_annotations
, jsr305
, and other libraries) and
for some reason it’s undesirable to add such dependency, it should be mentioned in Javadoc comments
for the respective fields and methods that accesses and calls to them should be protected by some
specified locks.
See [JCIP 2.4] for more information about @GuardedBy
.
Usage of @GuardedBy
is especially beneficial in conjunction with Error Prone tool which is able to statically check for unguarded accesses to fields
and methods with @GuardedBy annotations. There is
also an inspection "Unguarded field access" in IntelliJ IDEA with the same effect.
# Dc.8. If in a thread-safe class some fields are accessed both from within critical sections and outside of critical sections, is it explained in comments why this is safe? For example, unprotected read-only access to a reference to an immutable object might be benignly racy (see RC.5). Answering this question also helps to prevent problems described in IS.2, IS.3, and RC.2.
Instead of writing a comment explaining that access to a lazily initialized field outside of a
critical section is safe, the field could just be annotated with @LazyInit
from
error_prone_annotations
(but make
sure to read the Javadoc for this annotation and to check that the field conforms to the
description; LI.3 and LI.5 mention potential pitfalls).
Apart from the explanations why the partially blocking or racy code is safe, there should also be comments justifying such error-prone code and warning the developers that the code should be modified and reviewed with double attention: see NB.3.
There is an inspection "Field accessed in both synchronized and unsynchronized contexts" in IntelliJ IDEA which helps to find classes with unbalanced synchronization.
# Dc.9. Regarding every field with a volatile
modifier: does it really need
to be volatile
? Does the Javadoc comment for the field explain why the semantics of volatile
field reads and writes (as defined in the Java Memory Model) are required for the
field?
Similarly to what is noted in the previous item, justification for a lazily initialized field to be
volatile
could be omitted if the lazy initialization pattern itself is identified, according to
Dc.4. When volatile
on a field is needed to ensure safe publication of
objects written into it (see [JCIP 3.5] or here) or
linearizability of values observed by reader threads, then just mentioning
"safe publication" or "linearizable reads" in the Javadoc comment for the field is sufficient, it's
not needed to elaborate the semantics of volatile
which ensure the safe publication or the
linearizability.
By extension, this item also applies when an AtomicReference
(or a primitive atomic) is used
instead of raw volatile
, along with the consideration about unnecessary
atomic which might also be relevant in this case.
# Dc.10. Is it explained in the Javadoc comment for each mutable field in a
thread-safe class that is neither volatile
nor annotated with @GuardedBy
, why that is safe?
Perhaps, the field is only accessed and mutated from a single method or a set of methods that are
specified to be called only from a single thread sequentially (described as per
Dc.1). This recommendation also applies to final
fields that store objects of
non-thread-safe classes when those objects could be mutated from some methods of the enclosing
thread-safe class. See IS.2, IS.3,
RC.2, RC.3, and
RC.4 about what could go wrong with such code.
Insufficient synchronization
# IS.1. Can non-private static methods be called concurrently from multiple
threads? If there is a non-private static field with mutable state, such as a collection, is it an
instance of a thread-safe class or synchronized using some Collections.synchronizedXxx()
method?
Note that calls to DateFormat.parse()
and format()
must be synchronized because they mutate the
object: see IS.5.
# IS.2. There is no situation where some thread awaits until a
non-volatile field has a certain value in a loop, expecting it to be updated from another thread?
The field should at least be volatile
to ensure eventual visibility of concurrent updates. See
[JCIP 3.1, 3.1.4], and VNA00-J
for more details and examples.
Even if the respective field is volatile
, busy waiting for a condition in a loop can be abused
easily and therefore should be justified in a comment: see NB.4.
Dc.10 also demands adding explaining comments to mutable fields which are neither
volatile
nor annotated with @GuardedBy
which should inevitably lead to the discovery of the
visibility issue.
# IS.3. Read accesses to non-volatile primitive fields which can be
updated concurrently are protected with a lock as well as the writes? The minimum reason for this
is that reads of long
and double
fields are non-atomic (see JLS 17.7, [JCIP 3.1.2], VNA05-J).
But even with other types of fields, unbalanced synchronization creates possibilities for downstream
bugs related to the visibility (see the previous item) and the lack of the expected happens-before
relationships.
As well as with the previous item, accurate documentation of benign races (Dc.8 and Dc.10) should reliably expose the cases when unbalanced synchronization is problematic.
See also RC.2 regarding unbalanced synchronization of read accesses to mutable objects, such as collections.
There is a relevant inspection "Field accessed in both synchronized and unsynchronized contexts" in IntelliJ IDEA.
# IS.4. Is the business logic written for server frameworks thread-safe? This includes:
Servlet
implementations@(Rest)Controller
-annotated classes,@Get/PostMapping
-annotated methods in Spring@SessionScoped
and@ApplicationScoped
managed beans in JSFFilter
andHandler
implementations in various synchronous and asynchronous frameworks (including Jetty, Netty, Undertow)@GET
- and@POST
-annotated methods (resources) in JAX-RS (RESTful APIs)
It's easy to forget that if such code mutates some state (e. g. fields in the class), it must be properly synchronized or access only concurrent collections and classes.
# IS.5. Calls to parse()
and format()
on a shared instance of DateFormat
are
synchronized, e. g. if a DateFormat
is stored in a static field? Although parse()
and
format()
may look "read-only", they actually mutate the receiving DateFormat
object.
An inspection "Non thread-safe static field access" in IntelliJ IDEA helps to catch such concurrency bugs.
Excessive thread safety
# ETS.1. An example of excessive thread safety is a class where every modifiable
field is volatile
or an AtomicReference
or other atomic, and every collection field stores a
concurrent collection (e. g. ConcurrentHashMap
), although all accesses to those fields are
synchronized
.
There shouldn’t be any "extra" thread safety in code, there should be just enough of it. Duplication of thread safety confuses readers because they might think the extra thread safety precautions are (or used to be) needed for something but will fail to find the purpose.
The exception from this principle is the volatile
modifier on the lazily initialized field in the
safe local double-checked locking pattern
which is the recommended way to implement double-checked locking, despite that volatile
is
excessive for correctness
when the lazily initialized object has all final
fields*. Without that
volatile
modifier the thread safety of the double-checked locking could easily be broken by a
change (addition of a non-final field) in the class of lazily initialized objects, though that class
should not be aware of subtle concurrency implications. If the class of lazily initialized objects
is specified to be immutable (see Dc.3) the volatile
is still
unnecessary and the UnsafeLocalDCL
pattern could be used safely, but the fact that some class has all final
fields doesn’t
necessarily mean that it’s immutable.
See also the section about double-checked locking.
# ETS.2. Aren’t there AtomicReference
, AtomicBoolean
, AtomicInteger
or
AtomicLong
fields on which only get()
and set()
methods are called? Simple fields with
volatile
modifiers can be used instead, but volatile
might not be needed too; see
Dc.9.
# ETS.3. Does a class (method) need to be thread-safe? May a class be accessed (method called) concurrently from multiple threads (without happens-before relationships between the accesses or calls)? Can a class (method) be simplified by making it non-thread-safe?
See also Ft.1 about unneeded wrapping of a computation into a Future
and
Dc.9 about potentially unneeded volatile
modifiers.
This item is a close relative of Dn.1 (about rationalizing concurrency and thread safety in the patch description) and Dc.1 (about justifying concurrency in Javadocs for classes and methods, and documenting concurrent access). If these actions are done, it should be self-evident whether the class (method) needs to be thread-safe or not. There may be cases, however, when it might be desirable to make the class (method) thread-safe although it's not supposed to be accessed or called concurrently as of the moment of the patch. For example, thread safety may be needed to ensure memory safety (see CN.4 about this). Anticipating some changes to the codebase that make the class (method) being accessed from multiple threads may be another reason to make the class (method) thread-safe up front.
# ETS.4. Does a ReentrantLock
(or ReentrantReadWriteLock
, Semaphore
)
need to be fair? To justify the throughput penalty of making a lock fair it should be demonstrated
that a lack of fairness leads to unacceptably long starvation periods in some threads trying to
acquire the lock or pass the semaphore. This should be documented in the Javadoc comment for the
field holding the lock or the semaphore. See [JCIP 13.3] for more details.
Race conditions
# RC.1. Aren’t ConcurrentMap
(or Cache) objects updated with separate
containsKey()
, get()
, put()
and remove()
calls instead of a single call to
compute()
/computeIfAbsent()
/computeIfPresent()
/replace()
?
# RC.2. Aren’t there point read accesses such as Map.get()
,
containsKey()
or List.get()
outside of critical sections to a non-thread-safe collection such as
HashMap
or ArrayList
, while new entries can be added to the collection concurrently, even
though there is a happens-before edge between the moment when some entry is put into the collection
and the moment when the same entry is point-queried outside of a critical section?
The problem is that when new entries can be added to a collection, it grows and changes its internal
structure from time to time (HashMap rehashes the hash table, ArrayList
reallocates the internal
array). At such moments races might happen and unprotected point read accesses might fail with
NullPointerException
, ArrayIndexOutOfBoundsException
, or return null
or some random entry.
Note that this concern applies to ArrayList
even when elements are only added to the end of the
list. However, a small change in ArrayList
’s implementation in OpenJDK could have disallowed data
races in such cases at very little cost. If you are subscribed to the concurrency-interest mailing
list, you could help to bring attention to this problem by reviving this thread.
See also IS.3 regarding unbalanced synchronization of accesses to primitive fields.
# RC.3. A variation of the previous item: isn’t a non-thread-safe
collection such as HashMap
or ArrayList
iterated outside of a critical section, while it may
be modified concurrently? This could happen by accident when an Iterable
, Iterator
or Stream
over a collection is returned from a method of a thread-safe class, even though the iterator or
stream is created within a critical section. Note that returning unmodifiable collection views
like Collections.unmodifiableList()
from getters wrapping collection fields that may be modified
concurrently doesn't solve this problem. If the collection is relatively small, it should be
copied entirely, or a copy-on-write collection (see Sc.3) should be
used instead of a non-thread-safe collection.
Note that calling toString()
on a collection (e. g. in a logging statement) implicitly iterates
over it.
Like the previous item, this one applies to growing ArrayLists too.
This item applies even to synchronized collections: see RC.10 for details.
# RC.4. Generalization of the previous item: aren’t non-trivial objects that can be mutated concurrently returned from getters in a thread-safe class (and thus inevitably leaking outside of critical sections)?
# RC.5. If there are multiple variables in a thread-safe class that are
updated at once but have individual getters, isn’t there a race condition in the code that calls
those getters? If there is, the variables should be made final
fields in a dedicated POJO, that
serves as a snapshot of the updated state. The POJO is stored in a field of the thread-safe class,
directly or as an AtomicReference
. Multiple getters to individual fields should be replaced with
a single getter that returns the POJO. This allows avoiding a race condition in the client code by
reading a consistent snapshot of the state at once.
This pattern is also very useful for creating safe and reasonably simple non-blocking code: see NB.2 and [JCIP 15.3.1].
# RC.6. If some logic within some critical section depends on some data that principally is part of the internal mutable state of the class, but was read outside of the critical section or in a different critical section, isn’t there a race condition because the local copy of the data may become out of sync with the internal state by the time when the critical section is entered? This is a typical variant of check-then-act race condition, see [JCIP 2.2.1].
An example of this race condition is calling toArray()
on synchronized collections with a sized
array:
list = Collections.synchronizedList(new ArrayList<>());
...
elements = list.toArray(new Element[list.size()]);
This might unexpectedly leave the elements
array with some nulls in the end if there are some
concurrent removals from the list. Therefore, toArray()
on a synchronized collection should be
called with a zero-length array: toArray(new Element[0])
, which is also not worse from the
performance perspective: see "Arrays of Wisdom of the
Ancients".
See also RC.9 about cache invalidation races which are similar to check-then-act races.
# RC.7. Aren't there race conditions between the code (i. e. program runtime actions) and some actions in the outside world or actions performed by some other programs running on the machine? For example, if some configurations or credentials are hot reloaded from some file or external registry, reading separate configuration parameters or separate credentials (such as username and password) in separate transactions with the file or the registry may be racing with a system operator updating those configurations or credentials.
Another example is checking that a file exists (or not exists) and then reading, deleting, or
creating it, respectively, while another program or a user may delete or create the file between the
check and the act. It's not always possible to cope with such race conditions, but it's useful to
keep such possibilities in mind. Prefer static methods from java.nio.file.Files
class and
NIO file reading/writing API to methods from the old java.io.File
for file system operations.
Methods from Files
are more sensitive to file system race conditions and tend to throw exceptions
in adverse cases, while methods on File
swallow errors and make it hard even to detect race
conditions. Static methods from Files
also support StandardOpenOption.CREATE
and CREATE_NEW
which may help to ensure some extra atomicity.
# RC.8. If you are using Guava Cache and invalidate(key)
, are
you not affected by the race condition which can
leave a Cache
with an invalid (stale) value mapped for a key? Consider using Caffeine cache which doesn't have this problem. Caffeine is also faster and
more scalable than Guava Cache: see Sc.9.
# RC.9. Generalization of the previous item: isn't there a potential cache invalidation race in the code? There are several ways to get into this problem:
- Using
Cache.put()
method concurrently withinvalidate()
. Unlike RC.8, this is a race regardless of what caching library is used, not necessarily Guava. This is also similar to RC.1. - Having
put()
andinvalidate()
methods exposed in the own Cache interface. This places the burden of synchronizingput()
(together the preceding "checking" code, such asget()
) andinvalidate()
calls on the users of the API which really should be the job of the Cache implementation. - There is some lazily initialized state in a mutable object which can be invalidated upon mutation of the object, and can also be accessed concurrently with the mutation. This means the class is in the category of non-blocking concurrency: see the corresponding checklist items. A way to avoid cache invalidation race in this case is to wrap the primary state and the cached state into a POJO and replace it atomically, as described in NB.2.
# RC.10. The whole iteration loop over a synchronized collection
(i. e. obtained from one of the Collections.synchronizedXxx()
static factory methods), or a
Stream pipeline using a synchronized collection as a source is protected by synchronized (coll)
?
See the Javadoc
for examples and details.
This also applies to passing synchronized collections into:
- Copy constructors of other collections, e. g.
new ArrayList<>(synchronizedColl)
- Static factory methods of other collections, e. g.
List.copyOf()
,Set.copyOf()
,ImmutableMap.copyOf()
- Bulk methods on other collections:
otherColl.containsAll(synchronizedColl)
otherColl.addAll(synchronizedColl)
otherColl.removeAll(synchronizedColl)
otherMap.putAll(synchronizedMap)
otherColl.containsAll(synchronizedMap.keySet())
- Etc.
Because in all these cases there is an implicit iteration on the source collection.
See also RC.3 about unprotected iteration over non-thread-safe collections.
Testing
# T.1. Was it considered to add multi-threaded unit tests for a thread-safe class or method? Single-threaded tests don't really test the thread safety and concurrency. Note that this question doesn't mean to indicate that there must be concurrent unit tests for every piece of concurrent code in the project because correct concurrent tests take a lot of effort to write and therefore they might often have low ROI.
What is the worst thing that might happen if this code has a concurrency bug? This is a useful question to inform the decision about writing concurrent tests. The consequences may range from a tiny, entirely undetectable memory leak, to storing corrupted data in a durable database or a security breach.
# T.2. Isn't a shared java.util.Random
object used for data
generation in a concurrency test? java.util.Random
is synchronized internally, so if multiple
test threads (which are conceived to access the tested class concurrently) access the same
java.util.Random
object then the test might degenerate to a mostly synchronous one and fail to
exercise the concurrency properties of the tested class. See [JCIP 12.1.3]. Math.random()
is a
subject for this problem too because internally Math.random()
uses a globally shared
java.util.Random
instance. Use ThreadLocalRandom
instead.
# T.3. Do concurrent test workers coordinate their start using a latch
such as CountDownLatch
? If they don't much or even all of the test work might be done by the
first few started workers. See [JCIP 12.1.3] for more information.
# T.4. Are there more test threads than there are available
processors if possible for the test? This will help to generate more thread scheduling
interleavings and thus test the logic for the absence of race conditions more thoroughly. See
[JCIP 12.1.6] for more information. The number of available processors on the machine can be
obtained as Runtime.getRuntime().availableProcessors()
.
# T.5. Are there no regular assertions in code that is executed not in the main thread running the unit test? Consider the following example:
@Test public void testServiceListener() {
// Missed assertion -- Don't do this!
service.addListener(event -> Assert.assertEquals(Event.Type.MESSAGE_RECEIVED, event.getType()));
service.sendMessage("test");
}
Assuming the service
executes the code of listeners asynchronously in some internally-managed or
a shared thread pool, even if the assertion within the listener's lambda fails, JUnit and TestNG
will think the test has passed.
The solution to this problem is either to pass the data (or thrown exceptions) from a concurrent thread back to the main test thread and verify it in the end of the test, or to use ConcurrentUnit library which takes over the boilerplate associated with the first approach.
# T.6. Is the result of CountDownLatch.await()
method calls checked? The most frequent form of this mistake is forgetting to wrap
CountDownLatch.await()
into assertTrue()
in tests, which makes the test to not actually verify
that the production code works correctly. The absence of a check in production code might cause
race conditions.
Apart from CountDownLatch.await
, the other similar methods whose result must be checked are:
Lock.tryLock()
andtryAcquire()
methods onSemaphore
andRateLimiter
from GuavaMonitor.enter(...)
in GuavaCondition.await(...)
awaitTermination()
andawaitQuiescence()
methods. There is a separate item about them.Process.waitFor(...)
It's possible to find these problems using static analysis, e. g. by configuring the "Result of
method call ignored" inspection in IntelliJ IDEA to recognize Lock.tryLock()
,
CountDownLatch.await()
and other methods listed above. They are not in the default set of
checked methods, so they should be added manually in the inspection configuration.
Locks
# Lk.1. Is it possible to use concurrent collections and/or utilities from
java.util.concurrent.*
and avoid using locks with Object.wait()
/notify()
/notifyAll()
?
Code redesigned around concurrent collections and utilities is often both clearer and less
error-prone than code implementing the equivalent logic with intrinsic locks, Object.wait()
and
notify()
(Lock
objects with await()
and signal()
are not different in this regard). See
[EJ Item 81] for more information.
# Lk.2. Is it possible to simplify code that uses intrinsic locks or Lock
objects with conditional waits by using Guava’s Monitor
instead?
# Lk.3. Isn't ReentrantLock
used when synchronized
would suffice?
ReentrantLock
shoulndn't be used in the situations when none of its distinctive features
(tryLock()
, timed and interruptible locking methods, etc.) are used. Note that reentrancy is not
such a feature: intrinsic Java locks support reentrancy too. The ability for a ReentrantLock
to be
fair is seldom such a feature: see ETS.4. See [JCIP 13.4] for more information
about this.
This advice also applies when a class uses a private lock object (instead of synchronized (this)
or synchronized methods) to protect against accidental or malicious interference by the clients
acquiring synchronizing on the object of the class: see [JCIP 4.2.1], [EJ Item 82], LCK00-J.
# Lk.4. Locking (lock()
, lockInterruptibly()
, tryLock()
) and unlock()
methods are used strictly with the recommended try-finally idiom
without deviations?
lock()
(orlockInterruptibly()
) call goes before thetry {}
block rather than within it?- There are no statements between the
lock()
(orlockInterruptibly()
) call and the beginning of thetry {}
block? unlock()
call is the first statement within thefinally {}
block?
This advice doesn't apply when locking methods and unlock()
should occur in different scopes, i.
e. not within the recommended try-finally idiom altogether. The containing methods could be
annotated with Error Prone's @LockMethod
and
@UnlockMethod
annotations.
There is a "Lock acquired but not safely unlocked" inspection in IntelliJ IDEA which corresponds to this item.
See also LCK08-J.
Avoiding deadlocks
# Dl.1. If a thread-safe class is implemented so that there are nested critical sections protected by different locks, is it possible to redesign the code to get rid of nested critical sections? Sometimes a class could be split into several distinct classes, or some work that is done within a single thread could be split between several threads or tasks which communicate via concurrent queues. See [JCIP 5.3] for more information about the producer-consumer pattern.
There is an inspection "Nested 'synchronized' statement" in IntelliJ IDEA corresponding to this item.
# Dl.2. If restructuring a thread-safe class to avoid nested critical sections is not reasonable, was it deliberately checked that the locks are acquired in the same order throughout the code of the class? Is the locking order documented in the Javadoc comments for the fields where the lock objects are stored?
See LCK07-J for examples.
# Dl.3. If there are nested critical sections protected by several (potentially different) dynamically determined locks (for example, associated with some business logic entities), are the locks ordered before the acquisition? See [JCIP 10.1.2] for more information.
# Dl.4. Aren’t there calls to some callbacks (listeners, etc.) that can be configured through public API or extension interface calls within critical sections? With such calls, the system might be inherently prone to deadlocks because the external logic executed within a critical section may be unaware of the locking considerations and call back into the logic of the system, where some more locks may be acquired, potentially forming a locking cycle that might lead to a deadlock. Also, the external logic could just perform some time-consuming operation and by that harm the efficiency of the system (see Sc.1). See [JCIP 10.1.3] and [EJ Item 79] for more information.
When public API or extension interface calls happen within lambdas passed into Map.compute()
,
computeIfAbsent()
, computeIfPresent()
, and merge()
, there is a risk of not only deadlocks (see
the next item) but also race conditions which could result in a corrupted map (if it's not a
ConcurrentHashMap
, e. g. a simple HashMap
) or runtime exceptions.
Beware that a CompletableFuture
or a ListenableFuture
returned from a public API opens a door for performing some user-defined callbacks from the place
where the future is completed, deep inside the library (framework). If the future is completed
within a critical section, or from an ExecutorService
whose threads must not block, such as a
ForkJoinPool
(see TE.4) or the worker pool of an I/O library, consider either
returning a simple Future
, or documenting that stages shouldn't be attached to this
CompletableFuture
in the default execution mode. See TE.7 for more
information.
# Dl.5. Aren't there calls to methods on a ConcurrentHashMap
instance
within lambdas passed into compute()
-like methods called on the same map? For example, the
following code is deadlock-prone:
map.compute(key, (String k, Integer v) -> {
if (v == null || v == 0) {
return map.get(DEFAULT_KEY);
}
return v;
});
Note that nested calls to non-lambda accepting methods, including read-only access methods like
get()
create the possibility of deadlocks as well as nested calls to compute()
-like methods
because the former are not always lock-free.
Improving scalability
# Sc.1. Are critical sections as small as possible? For every critical section: can’t some statements in the beginning and the end of the section be moved out of it? Not only minimizing critical sections improves scalability, but also makes it easier to review them and spot race conditions and deadlocks.
This advice equally applies to lambdas passed into ConcurrentHashMap
’s compute()
-like methods.
See also [JCIP 11.4.1] and [EJ Item 79].
# Sc.2. Is it possible to increase locking granularity? If a
thread-safe class encapsulates accesses to map, is it possible to turn critical sections into
lambdas passed into ConcurrentHashMap.compute()
or computeIfAbsent()
or computeIfPresent()
methods to enjoy effective per-key locking granularity? Otherwise, is it possible to use
Guava’s Striped
or an equivalent? See
[JCIP 11.4.3] for more information about lock striping.
# Sc.3. Is it possible to use non-blocking collections instead of blocking ones? Here are some possible replacements within JDK:
Collections.synchronizedMap(HashMap)
,Hashtable
→ConcurrentHashMap
Collections.synchronizedSet(HashSet)
→ConcurrentHashMap.newKeySet()
Collections.synchronizedMap(TreeMap)
→ConcurrentSkipListMap
. By the way,ConcurrentSkipListMap
is not the state of the art concurrent sorted dictionary implementation. SnapTree is more efficient thanConcurrentSkipListMap
and there have been some research papers presenting algorithms that are claimed to be more efficient than SnapTree.Collections.synchronizedSet(TreeSet)
→ConcurrentSkipListSet
Collections.synchronizedList(ArrayList)
,Vector
→CopyOnWriteArrayList
LinkedBlockingQueue
→ConcurrentLinkedQueue
LinkedBlockingDeque
→ConcurrentLinkedDeque
Consider also using queues from JCTools instead of concurrent queues from the JDK: see Sc.8.
See also an item about using ForkJoinPool
instead of newFixedThreadPool(N)
for high-traffic executor services, which internally amounts to replacing a single blocking queue of
tasks inside ThreadPoolExecutor
with multiple non-blocking queues inside ForkJoinPool
.
# Sc.4. Is it possible to use ClassValue
instead of
ConcurrentHashMap<Class, ...>
? Note, however, that unlike ConcurrentHashMap
with its
computeIfAbsent()
method ClassValue
doesn’t guarantee that per-class value is computed only
once, i. e. ClassValue.computeValue()
might be executed by multiple concurrent threads. So if the
computation inside computeValue()
is not thread-safe, it should be synchronized separately. On the
other hand, ClassValue
does guarantee that the same value is always returned from
ClassValue.get()
(unless remove()
is called).
# Sc.5. Was it considered to replace a simple lock with a ReadWriteLock
?
Beware, however, that it’s more expensive to acquire and release a ReentrantReadWriteLock
than a
simple intrinsic lock, so the increase in scalability comes at the cost of reduced throughput. If
the operations to be performed under a lock are short, or if a lock is already striped (see
Sc.2) and therefore very lightly contended, replacing a simple
lock with a ReadWriteLock
might have a net negative effect on the application performance. See
this comment
for more details.
# Sc.6. Is it possible to use a StampedLock
instead of a ReentrantReadWriteLock
when reentrancy is not needed?
# Sc.7. Is it possible to use LongAdder
for "hot fields" (see [JCIP 11.4.4]) instead of AtomicLong
or AtomicInteger
on which only
methods like incrementAndGet()
, decrementAndGet()
, addAndGet()
and (rarely) get()
is called,
but not set()
and compareAndSet()
?
Note that a field should be really updated from several concurrent threads steadily to justify using
LongAdder
. If the field is usually updated only from one thread at a time (there may be several
updating threads, but each of them accesses the field infrequently, so the updates from different
threads rarely happen at the same time) it's still better to use AtomicLong
or AtomicInteger
because they take less memory than LongAdder
and their updates are cheaper.
# Sc.8. Was it considered to use one of the array-based queues from the JCTools
library instead of ArrayBlockingQueue
?
Those queues from JCTools are classified as blocking, but they avoid lock acquisition in many cases
and are generally much faster than ArrayBlockingQueue
.
See also Sc.3 regarding replacing blocking queues (and other collections) with non-blocking equivalents within JDK.
# Sc.9. Was it considered to use Caffeine cache instead of other Cache implementations (such from Guava)? Caffeine's performance is very good compared to other caching libraries.
Another reason to use Caffeine instead of Guava Cache is that it avoids an invalidation race: see RC.8.
# Sc.10. When some state or a condition is checked, or resource is allocated within
a critical section, and the result is usually expected to be positive (access granted,
resource allocated) because the entity is rarely in a protected, restricted, or otherwise special
state, or because the underlying resource is rarely in shortage, is it possible to apply
speculation (optimistic concurrency) to improve scalability? This means to use lighter-weight
synchronization (e. g. shared locking with a ReadWriteLock
or a StampedLock
instead of exclusive
locking) sufficient just to detect a shortage of the resource or that the entity is in a special
state, and fallback to heavier synchronization only when necessary.
This principle is used internally in many scalable concurrent data structures, including
ConcurrentHashMap
and JCTools's queues, but could be applied on the higher logical level as well.
See also the article about Optimistic concurrency control on Wikipedia.
# Sc.11. Was it considered to use a ForkJoinPool
instead of a
ThreadPoolExecutor
with N threads (e. g. returned from one of Executors.newFixedThreadPool()
methods), for thread pools on which a lot of small tasks are executed? ForkJoinPool
is more
scalable because internally it maintains one queue per each worker thread, whereas
ThreadPoolExecutor
has a single, blocking task queue shared among all threads.
ForkJoinPool
implements ExecutorService
as well as ThreadPoolExecutor
, so could often be a
drop in replacement. For caveats and details, see this and this messages by Doug Lea.
See also items about using non-blocking collections (including queues) instead of blocking ones and about using JCTools queues.
Lazy initialization and double-checked locking
Regarding all items in this section, see also [EJ Item 83] and "Safe Publication this and Safe Initialization in Java".
# LI.1. For every lazily initialized field: is the initialization code thread-safe and might it be called from multiple threads concurrently? If the answers are "no" and "yes", either double-checked locking should be used or the initialization should be eager.
Be especially wary of using lazy-initialization in mutable objects. They are prone to cache invalidation race conditions: see RC.9.
# LI.2. If a field is initialized lazily under a simple lock, is it possible to use double-checked locking instead to improve performance?
# LI.3. Does double-checked locking follow the SafeLocalDCL pattern, as noted in ETS.1?
If the initialized objects are immutable a more efficient UnsafeLocalDCL
pattern might also be used. However, if the lazily-initialized field is not volatile
and there are
accesses to the field that bypass the initialization path, the value of the field must be
carefully cached in a local variable. For example, the following code is buggy:
private MyImmutableClass lazilyInitializedField;
void doSomething() {
...
if (lazilyInitializedField != null) { // (1)
lazilyInitializedField.doSomethingElse(); // (2) - Can throw NPE!
}
}
This code might result in a NullPointerException
, because although a non-null value is observed
when the field is read the first time at line 1, the second read at line 2 could observe null.
The above code could be fixed as follows:
void doSomething() {
MyImmutableClass lazilyInitialized = this.lazilyInitializedField;
if (lazilyInitialized != null) {
// Calling doSomethingElse() on a local variable to avoid NPE:
// see https://github.com/code-review-checklists/java-concurrency#safe-local-dcl
lazilyInitialized.doSomethingElse();
}
}
See "Wishful Thinking: Happens-Before Is The Actual Ordering" and "Date-Race-Ful Lazy Initialization for Performance" for more information.
# LI.4. In each particular case, doesn’t the net impact of double-checked locking and lazy field initialization on performance and complexity overweight the benefits of lazy initialization? Isn’t it ultimately better to initialize the field eagerly?
# LI.5. If a field is initialized lazily under a simple lock or using
double-checked locking, does it really need locking? If nothing bad may happen if two threads do the
initialization at the same time and use different copies of the initialized state then a benign race
could be allowed. The initialized field should still be volatile
(unless the initialized objects
are immutable) to ensure there is a happens-before edge between threads doing the initialization and
reading the field. This is called a single-check idiom (or a racy single-check idiom if the
field doesn't have a volatile
modifier) in [EJ Item 83].
Annotate such fields with @LazyInit
from
error_prone_annotations
. The place
in code with the race should also be identified with WARNING comments: see
NB.3.
# LI.6. Is lazy initialization holder class idiom used for static fields which must be lazy rather than double-checked locking? There are no reasons to use double-checked locking for static fields because lazy initialization holder class idiom is simpler, harder to make mistake in, and is at least as efficient as double-checked locking (see benchmark results in "Safe Publication and Safe Initialization in Java").
Non-blocking and partially blocking code
# NB.1. If there is some non-blocking or semi-symmetrically blocking code that mutates the state of a thread-safe class, was it deliberately checked that if a thread on a non-blocking mutation path is preempted after each statement, the object is still in a valid state? Are there enough comments, perhaps before almost every statement where the state is changed, to make it relatively easy for readers of the code to repeat and verify the check?
# NB.2. Is it possible to simplify some non-blocking code by confining
all mutable state in an immutable POJO and update it via compare-and-swap operations? This pattern
is also mentioned in RC.5. Instead of a POJO, a single long
value could be
used if all parts of the state are integers that can together fit 64 bits. See also [JCIP 15.3.1].
# NB.3. Are there visible WARNING comments identifying the boundaries of non-blocking code? The comments should mark the start and the end of non-blocking code, partially blocking code, and benignly racy code (see Dc.8 and LI.5). The opening comments should:
- Justify the need for such error-prone code (which is a special case of Dc.1).
- Warn developers that changes in the following code should be made (and reviewed) extremely carefully.
# NB.4. If some condition is awaited in a (busy) loop, like in the following example:
volatile boolean condition;
// in some method:
while (!condition) {
// Or Thread.sleep/yield/onSpinWait, or no statement, i. e. a pure spin wait
TimeUnit.SECONDS.sleep(1L);
}
// ... do something when condition is true
Is it explained in a comment why busy waiting is needed in the specific case, and why the costs and potential problems associated with busy waiting (see [JCIP 12.4.2] and [JCIP 14.1.1]) either don't apply in the specific case or are outweighed by the benefits?
If there is no good reason for spin waiting, it's preferable to synchronize explicitly using a tool
such as Semaphore
,
CountDownLatch
, or Exchanger
,
or if the logic for which the spin loop awaits is executed in some ExecutorService
, it's better to
add a callback to the corresponding CompletableFuture
or ListenableFuture
(check TE.7
about doing this properly).
In test code waiting for some condition, a library such as Awaitility could be used instead of explicit looping with
Thread.sleep
calls.
Since Thread.yield()
and Thread.onSpinWait()
are rarely, if ever, useful outside of spin loops,
this item could also be interpreted as that there should be a comment to every call to either of
these methods, explaining either why they are called outside of a spin loop, or justifying the spin
loop itself.
In any case, the field checked in the busy loop must be volatile
: see
IS.2 for details.
The busy wait pattern is covered by IntelliJ IDEA's inspections "Busy wait" and "while loop spins on field".
Threads and Executors
# TE.1. Are Threads given names when created? Are ExecutorServices created with thread factories that name threads?
It appears that different projects have different policies regarding other aspects of Thread
creation: whether to make them daemon with setDaemon()
, whether to set thread priorities and
whether a ThreadGroup
should be specified. Many of such rules can be effectively enforced with
forbidden-apis.
# TE.2. Aren’t there threads created and started, but not stored in fields, a-la
new Thread(...).start()
, in some methods that may be called repeatedly? Is it possible to
delegate the work to a cached or a shared ExecutorService
instead?
Another form of this problem is when a Thread
(or an ExecutorService
) is created and managed
within objects (in other words, active objects) that
are relatively short-lived. Is it possible to reuse executors by creating them one level up the
stack and passing shared executors to constructors of the short-lived objects, or a shared
ExecutorService
stored in a static field?
# TE.3. Aren’t some network I/O operations performed in an
Executors.newCachedThreadPool()
-created ExecutorService
? If a machine that runs the
application has network problems or the network bandwidth is exhausted due to increased load,
CachedThreadPools that perform network I/O might begin to create new threads uncontrollably.
Note that completing some CompletableFuture
or SettableFuture
from inside a cached thread pool
and then returning this future to a user might expose the thread pool to executing unwanted actions
if the future is used improperly: see TE.7 for details.
# TE.4. Aren’t there blocking or I/O operations performed in tasks scheduled
to a ForkJoinPool
(except those performed via a managedBlock()
call)? Parallel Stream
operations are executed in the common ForkJoinPool
implicitly, as well
as the lambdas passed into CompletableFuture
’s methods whose names end with "Async" but not
accepting a custom executor.
Note that attaching blocking or I/O operations to a CompletableFuture
as stage in default
execution mode (via methods like thenAccept()
, thenApply()
, handle()
, etc.) might also
inadvertently lead to performing them in ForkJoinPool
from where the future may be completed: see
TE.7.
Thread.sleep()
is a blocking operation.
This advice should not be taken too far: occasional transient IO (such as that may happen during
logging) and operations that may rarely block (such as ConcurrentHashMap.put()
calls) usually
shouldn’t disqualify all their callers from execution in a ForkJoinPool
or in a parallel Stream
.
See Parallel Stream Guidance for the
more detailed discussion of these tradeoffs.
See also the section about parallel Streams.
# TE.5. An opposite of the previous item: can non-blocking computations be
parallelized or executed asynchronously by submitting tasks to ForkJoinPool.commonPool()
or via
parallel Streams instead of using a custom thread pool (e. g. created by one of the static factory
methods from ExecutorServices
)? Unless the custom thread pool is configured with a ThreadFactory
that specifies a non-default priority for threads or a custom exception handler (see
TE.1) there is little reason to create more threads in the system instead of
reusing threads of the common ForkJoinPool
.
# TE.6. Is every ExecutorService
treated as a resource and is shut down
explicitly in the close()
method of the containing object, or in a try-with-resources of a
try-finally statement? Failure to shutdown an ExecutorService
might lead to a thread leak even if
an ExecutorService
object is no longer accessible, because some implementations (such as
ThreadPoolExecutor
) shutdown themselves in a finalizer, while finalize()
is not guaranteed to
ever be called by
the JVM.
To make explicit shutdown possible, first, ExecutorService
objects must not be assinged into
variables and fields of Executor
type.
# TE.7. Are non-async stages attached to a CompletableFuture
simple and
non-blocking unless the future is completed from a thread in the same thread pool as the thread from where a CompletionStage
is attached?
This also applies when asynchronous callback is attached using Guava's
ListenableFuture.addListener()
or Futures.addCallback()
methods and directExecutor()
(or an equivalent) is provided as the executor for the callback.
Non-async execution is called default execution (or default mode) in the documentation for
CompletionStage
:
these are methods thenApply()
, thenAccept()
, thenRun()
, handle()
, etc. Such stages may be
executed either from the thread adding a stage, or from the thread calling future.complete()
.
If the CompletableFuture
originates from a library, it's usually unknown in which thread
(executor) it is completed, therefore, chaining a heavyweight, blocking, or I/O operation to such a
future might lead to problems described in TE.3,
TE.4 (if the future is completed from a ForkJoinPool
or an event loop executor
in an asynchronous library), and Dl.4.
Even if the CompletableFuture
is created in the same codebase as stages attached to it, but is
completed in a different thread pool, default stage execution mode leads to non-deterministic
scheduling of operations. If these operations are heavyweight and/or blocking, this reduces the
system's operational predictability and robustness, and also creates a subtle dependency between the
components: e. g. if the component which completes the future decides to migrate this action to a
ForkJoinPool
, it could suddenly lead to the problems described in the previous paragraph.
A lightweight, non-blocking operation which is OK to attach to a CompletableFuture
as a non-async
stage may be something like incrementing an AtomicInteger
counter, adding an element to a
non-blocking queue, putting a value into a ConcurentHashMap
, or a logging statement.
It's also fine to attach a stage in the default mode if preceded with if (future.isDone())
check
which guarantees that the completion stage will be executed immediately in the current thread
(assuming the current thread belongs to the proper thread pool to perform the stage action).
The specific reason(s) making non-async stage or callback attachment permissible (future completion
and stage attachment happening in the same thread pool; simple/non-blocking callback; or
future.isDone()
check) should be identified in a comment.
See also the Javadoc for ListenableFuture.addListener()
describing this problem.
# TE.8. Is it possible to execute a task or an action with a delay via a
ScheduledExecutorService
rather than by calling Thread.sleep()
before performing the work or submitting the task to
an executor? ScheduledExecutorService
allows to execute many such tasks on a small number of
threads, while the approach with Thread.sleep
requires a dedicated thread for every delayed
action. Sleeping in the context of an unknown executor (if there is insufficient concurrent access
documentation for the method, as per Dc.1, or if this is a
concurrency-agnostic library method) before submitting the task to an executor is also bad: the
context executor may not be well-suited for blocking calls such as Thread.sleep
, see
TE.4 for details.
This item equally applies to scheduling one-shot and recurrent delayed actions, there are methods
for both scenarios in ScheduledExecutorService
.
Be cautious, however, about scheduling tasks with affinity to system time or UTC time (e. g.
beginning of each hour) using ScheduledThreadPoolExecutor
: it can experience unbounded clock
drift.
# TE.9. The result of ExecutorService.awaitTermination()
method
calls is checked? Calling awaitTermination()
(or ForkJoinPool.awaitQuiescence()
) and not
checking the result makes little sense. If it's actually important to await termination, e. g. to
ensure a happens-before relation between the completion of the actions scheduled to the
ExecutorService
and some actions following the awaitTermination()
call, or because termination
means a release of some heavy resource and if the resource is not released there is a noticeable
leak, then it is reasonable to at least check the result of awaitTermination()
and log a warning
if the result is negative, making debugging potential problems in the future easier. Otherwise, if
awaiting termination really makes no difference, then it's better to not call awaitTermination()
at all.
Apart from ExecutorService
, this item also applies to awaitTermination()
methods on
AsynchronousChannelGroup
and io.grpc.ManagedChannel
from gRPC-Java.
It's possible to find omitted checks for awaitTermination()
results using Structural search
inspection in
IntelliJ IDEA with the following pattern:
$x$.awaitTermination($y$, $z$);
See also a similar item about not checking the result of CountDownLatch.await()
.
# TE.10. Isn't ExecutorService
assigned into a variable or a
field of Executor
type? This makes it impossible to follow the practice of explicit shutdown of
ExecutorService
objects.
In IntelliJ IDEA, it's possible to find violations of this practice automatically using two patterns added to Structural Search inspection:
- "Java" pattern:
$x$ = $y$
, where the "Type" of$x$
isExecutor
("within type hierarchy" flag is off) and the "Type" of$y$
isExecutorService
("within type hierarchy" flag is on). - "Java - Class Member" pattern:
$Type$ $x$ = $y$;
, where the "Text" of$Type$
isExecutor
and the "Type" of$y$
isExecutorService
(within type hierarchy).
# TE.11. Isn't ScheduledExecutorService
assigned into
a variable or a field of ExecutorService
type? This is wasteful because the primary Java
implementation of ScheduledExecutorService
, ScheduledThreadPoolExecutor
(it is returned from Executors.newScheduledThreadPool()
and newSingleThreadScheduledExecutor()
static factory methods) uses a PriorityQueue
internally to manage tasks which incurs higher memory
footprint and CPU overhead compared to non-scheduled ExecutorService
implementations such as
vanilla ThreadPoolExecutor
or ForkJoinPool
.
This problem could be caught statically in a way similar to what is described in the previous item.
Parallel Streams
# PS.1. For every use of parallel Streams via
Collection.parallelStream()
or Stream.parallel()
: is it explained why parallel Stream
is
used in a comment preceding the stream operation? Are there back-of-the-envelope calculations or
references to benchmarks showing that the total CPU time cost of the parallelized computation
exceeds 100 microseconds?
Is there a note in the comment that parallelized operations are generally I/O-free and non-blocking,
as per TE.4? The latter might be obvious momentary, but as codebase evolves the
logic that is called from the parallel stream operation might become blocking accidentally. Without
comment, it’s harder to notice the discrepancy and the fact that the computation is no longer a good
fit for parallel Streams. It can be fixed by calling the non-blocking version of the logic again or
by using a simple sequential Stream
instead of a parallel Stream
.
Futures
# Ft.1. Does a method returning a Future
do some blocking operation
asynchronously? If it doesn't, was it considered to perform non-blocking computation logic and
return the result directly from the method, rather than within a Future
? There are situations
when someone might still want to return a Future
wrapping some non-blocking computation,
essentially relieving the users from writing boilerplate code like
CompletableFuture.supplyAsync(obj::expensiveComputation)
if all of them want to run the method
asynchronously. But if at least some of the clients don't need the indirection, it's better not to
wrap the logic into a Future
prematurely and give the users of the API a choice to do this
themselves.
See also ETS.3 about unneeded thread-safety of a method.
# Ft.2. Aren't there blocking operations in a method returning a
Future
before asynchronous execution is started, and is it started at all? Here is the
antipattern:
// DON'T DO THIS
Future<Salary> getSalary(Employee employee) throws ConnectionException {
Branch branch = retrieveBranch(employee); // A database or an RPC call
return CompletableFuture.supplyAsync(() -> {
return retrieveSalary(branch, employee); // Another database or an RPC call
}, someBlockingIoExecutor());
}
Blocking the caller thread is unexpected for a user seeing a method returning a Future
.
An example completely without asynchrony:
// DON'T DO THIS
Future<Salary> getSalary(Employee employee) throws ConnectionException {
SalaryDTO salaryDto = retrieveSalary(employee); // A database or an RPC call
Salary salary = toSalary(salaryDto);
return completedFuture(salary); // Or Guava's immediateFuture(), Scala's successful()
}
If the retrieveSalary()
method is not blocking itself, the getSalary()
may not need to return
a Future
.
Another problem with making blocking calls before scheduling an Future
is that the resulting code
has multiple failure paths: either the future may complete
exceptionally, or the method itself may throw an exception (typically from the blocking operation),
which is illustrated by getSalary() throws ConnectionException
in the above examples.
This advice also applies when a method returns any object representing an asynchronous execution
other than Future
, such as Deferred
, Flow.Publisher
, org.reactivestreams.Publisher
,
or RxJava's Observable
.
# Ft.3. If a method returns a Future
and some logic in the
beginning of it may lead to an expected failure (i. e. not a result of a programming bug), was
it considered to propagate an expected failure by a Future
completed exceptionally, rather than
throwing from the method? For example, the following method:
Future<Response> makeQuery(String query) throws InvalidQueryException {
Request req = compile(query); // Can throw an InvalidQueryException
return CompletableFuture.supplyAsync(() -> service.remoteCall(req), someBlockingIoExecutor());
}
May be converted into:
Future<Response> makeQuery(String query) {
try {
Request req = compile(query);
} catch (InvalidQueryException e) {
// Explicit catch preserves the semantics of the original version of makeQuery() most closely.
// If compile(query) is an expensive computation, it may be undesirable to schedule it to
// someBlockingIoExecutor() by simply moving compile(query) into the lambda below because if
// this pool has more threads than CPUs then too many compilations might be started in parallel,
// leading to excessive switches between threads running CPU-bound tasks.
// Another alternative is scheduling compile(query) to the common FJP:
// CompletableFuture.supplyAsync(() -> compile(query))
// .thenApplyAsync(service::remoteCall, someBlockingIoExecutor());
CompletableFuture<Response> f = new CompletableFuture<>();
f.completeExceptionally(e);
return f; // Or use Guava's immediateFailedFuture()
}
return CompletableFuture.supplyAsync(() -> service.remoteCall(req), someBlockingIoExecutor());
}
The point of this refactoring is unification of failure paths, so that the users of the API don't have to deal with multiple different ways of handling errors from the method.
Similarly to the previous item, this consideration also applies when
a method returns any object representing an asynchronous execution other than Future
, such as
Deferred
, Publisher
, or Observable
.
Thread interruption and Future
cancellation
# IF.1. If some code propagates InterruptedException
wrapped into another
exception (e. g. RuntimeException
), is the interruption status of the current thread restored
before the wrapping exception is thrown?
Propagating InterruptedException
wrapped into another exception is a controversial practice
(especially in libraries) and it may be prohibited in some projects completely, or in specific
subsystems.
# IF.2. If some method returns normally after catching an
InterruptedException
, is this coherent with the (documented) semantics of the method? Returning
normally after catching an InterruptedException
usually makes sense only in two types of methods:
Runnable.run()
orCallable.call()
themselves, or methods that are intended to be submitted as tasks to some Executors as method references.Thread.currentThread().interrupt()
should still be called before returning from the method, assuming that the interruption policy of the threads in theExecutor
is unknown.- Methods with "try" or "best effort" semantics. Documentation for such methods should be clear
that they stop attempting to do something when the thread is interrupted, restore the interruption
status of the thread and return. For example,
log()
orsendMetric()
could probably be such methods, as well asboolean trySendMoney()
, but notvoid sendMoney()
.
If a method doesn’t fall into either of these categories, it should propagate InterruptedException
directly or wrapped into another exception (see the previous item), or it should not return normally
after catching an InterruptedException
, but rather continue execution in some sort of retry loop,
saving the interruption status and restoring it before returning (see an example from JCIP). Fortunately, in most situations, it’s
not needed to write such boilerplate code: one of the methods from Uninterruptibles
utility class from Guava can be used.
# IF.3. If an InterruptedException
or a TimeoutException
is caught on a
Future.get()
call and the task behind the future doesn’t have side effects, i. e. get()
is
called only to obtain and use the result in the context of the current thread rather than achieve
some side effect, is the future canceled?
See [JCIP 7.1] for more information about thread interruption and task cancellation.
Time
# Tm.1. Are values returned from System.nanoTime()
compared in an
overflow-aware manner, as described in the documentation for
this method?
# Tm.2. Isn't System.currentTimeMillis()
used for time comparisons,
timed blocking, measuring intervals, timeouts, etc.? System.currentTimeMillis()
is a subject to
the "time going backward" phenomenon. This might happen due to a time correction on a server, for
example.
System.nanoTime()
should be used instead of currentTimeMillis()
for the purposes of time
comparision, interval measurements, etc. Values returned from nanoTime()
never decrease (but may
overflow — see the previous item). Warning: nanoTime()
didn’t always uphold to this guarantee in
OpenJDK until 8u192 (see JDK-8184271). Make sure
to use the freshest distribution.
In distributed systems, the leap second adjustment causes similar issues.
# Tm.3. Do variables that store time limits and periods have suffixes identifying
their units, for example, "timeoutMillis" (also -Seconds, -Micros, -Nanos) rather than just
"timeout"? In method and constructor parameters, an alternative is providing a TimeUnit
parameter next to a "timeout" parameter. This is the preferred option for public APIs.
# Tm.4. Do methods that have "timeout" and "delay" parameters
treat negative arguments as zeros? This is to obey the principle of least astonishment because all
timed blocking methods in classes from java.util.concurrent.*
follow this convention.
# Tm.5. Tasks that should happen at a certain system time, UTC
time, or wall-clock time far in the future, or run periodically with a cadence expressed in terms of
system/UTC/wall-clock time (rather than internal machine's CPU time) are not scheduled with
ScheduledThreadPoolExecutor
? ScheduledThreadPoolExecutor
(this class is also behind all
factory methods in Executors
which return a ScheduledExecutorService
) uses System.nanoTime()
for timing intervals. nanoTime()
can drift against the system time and the UTC time.
CronScheduler
is a scheduling class designed
to be proof against unbounded clock drift relative to UTC or system time for both one-shot or
periodic tasks. See more detailed recommendations on choosing between
ScheduledThreadPoolExecutor
and CronScheduler
.
On Android, use Android-specific APIs.
# Tm.6. On consumer devices (PCs, laptops, tables, phones),
ScheduledThreadPoolExecutor
(or Timer
) is not used for human interaction tasks or
interactions between the device and a remote service? Examples of human interaction tasks are
alarms, notifications, timers, or task management. Examples of interactions between user's device
and remote services are checking for new e-mails or messages, widget updates, or software updates.
The reason for this is that neither ScheduledThreadPoolExecutor
nor Timer
account for machine
suspension
(such as sleep or hibernation mode). On Android, use Android-specific APIs instead.
Consider CronScheduler as a replacement for
ScheduledThreadPoolExecutor
in these cases for end-user JVM apps.
ThreadLocal
# TL.1. Can ThreadLocal
field be static final
? There are three cases
when a ThreadLocal
cannot be static:
- It holds some state specific to the containing instance object, rather than, for example,
reusable objects to avoid allocations (which would be the same for all
ThreadLocal
-containing instances). - A method using a
ThreadLocal
may call another method (or the same method, recursively) that also uses thisThreadLocal
, but on a different containing object. - There is a class (or
enum
) modelling a specific type ofThreadLocal
usage, and there are only limited number of instances of this class in the JVM: i. e. all are constants stored instatic final
fields, orenum
constants.
If a usage of ThreadLocal
doesn't fall into either of these categories, it can be static final
.
There is an inspection "ThreadLocal field not declared static final" in IntelliJ IDEA which corresponds to this item.
Static ThreadLocal
fields could also be enforced using Checkstyle, using the following combination
of checks:
<!-- Enforce 'private static final' order of modifiers -->
<module name="ModifierOrder" />
<!-- Ensure all ThreadLocal fields are private -->
<!-- Requires https://github.com/sevntu-checkstyle/sevntu.checkstyle -->
<module name="AvoidModifiersForTypesCheck">
<property name="forbiddenClassesRegexpProtected" value="ThreadLocal"/>
<property name="forbiddenClassesRegexpPublic" value="ThreadLocal"/>
<property name="forbiddenClassesRegexpPackagePrivate" value="ThreadLocal"/>
</module>
<!-- Prohibit any ThreadLocal field which is not private static final -->
<module name="Regexp">
<property name="id" value="nonStaticThreadLocal"/>
<property name="format"
value="^\s*private\s+(ThreadLocal|static\s+ThreadLocal|final\s+ThreadLocal)"/>
<property name="illegalPattern" value="true"/>
<property name="message" value="Non-static final ThreadLocal"/>
</module>
# TL.2. Doesn't a ThreadLocal
mask issues with the code, such as poor
control flow or data flow design? Is it possible to redesign the system without using
ThreadLocal
, would that be simpler? This is especially true for instance-level (non-static)
ThreadLocal
fields; see also TL.1 and TL.4 about them.
See Dc.2 about the importance of articulating the control flow and the data flow of a subsystem which may help to uncover other issues with the design.
# TL.3. Isn't a ThreadLocal
used only to reuse some small heap
objects, cheap to allocate and initialize, that would otherwise need to be allocated relatively
infrequently? In this case, the cost of accessing a ThreadLocal
would likely outweigh the
benefit from reducing allocations. The evidence should be supplied that introducing a ThreadLocal
shortens the GC pauses and/or increases the overall throughput of the system.
# TL.4. If the threads which execute code with usage of a non-static
ThreadLocal
are long-living and there is a fixed number of them (e. g. workers of a fixed-sized
ThreadPoolExecutor
) and there is a greater number of shorter-living ThreadLocal
-containing
objects, was it considered to replace the instance-level ThreadLocal<Val>
with a
ConcurrentHashMap<Thread, Val> threadLocalValues
confined to the objects, accessed like
threadLocalValues.get(Thread.currentThread())
? This approach requires some confidence and
knowledge about the threading model of the subsystem (see Dc.2), though it
may also be trivial if Active Object pattern is used (see Dn.2), but is much
friendlier to GC because no short-living weak references are produced.
Thread safety of Cleaners and native code
# CN.1. If a class manages native resources and employs
java.lang.ref.Cleaner
(or sun.misc.Cleaner
; or overrides Object.finalize()
) to ensure that
resources are freed when objects of the class are garbage collected, and the class implements
Closeable
with the same cleanup logic executed from close()
directly rather than through
Cleanable.clean()
(or sun.misc.Cleaner.clean()
) to be able to distinguish between explicit
close()
and cleanup through a cleaner (for example, clean()
can log a warning about the object
not being closed explicitly before freeing the resources), is it ensured that even if the cleanup
logic is called concurrently from multiple threads, the actual cleanup is performed only once? The
cleanup logic in such classes should obviously be idempotent because it’s usually expected to be
called twice: the first time from the close()
method and the second time from the cleaner or
finalize()
. The catch is that the cleanup must be concurrently idempotent, even if close()
is
never called concurrently on objects of the class. That’s because the garbage collector may
consider the object to become unreachable before the end of a close()
call and initiate cleanup
through the cleaner or finalize()
while close()
is still being executed.
Alternatively, close()
could simply delegate to Cleanable.clean()
(sun.misc.Cleaner.clean()
)
which is concurrently idempotent itself. But then it’s impossible to distinguish between explicit
and automatic cleanup.
See also JLS 12.6.2.
# CN.2. In a class with some native state that has a cleaner or overrides
finalize()
, are bodies of all methods that interact with the native state wrapped with
try { ... } finally { Reference.reachabilityFence(this); }
,
including constructors and the close()
method, but excluding finalize()
? This is needed because
an object could become unreachable and the native memory might be freed from the cleaner while the
method that interacts with the native state is being executed, that might lead to use-after-free or
JVM memory corruption.
reachabilityFence()
in close()
also eliminates the race between close()
and the cleanup
executed through the cleaner or finalize()
(see the previous item), but it may be a good idea to
retain the thread safety precautions in the cleanup procedure, especially if the class in question
belongs to the public API of the project because otherwise if close()
is accidentally or
maliciously called concurrently from multiple threads, the JVM might crash due to double memory free
or, worse, memory might be silently corrupted, while the promise of the Java platform is that
whatever buggy some code is, as long as it passes bytecode verification, thrown exceptions should be
the worst possible outcome, but the virtual machine shouldn’t crash. CN.4
also stresses on this principle.
Reference.reachabilityFence()
has been added in JDK 9. If the project targets JDK 8 and Hotspot
JVM, any method with an empty body is an effective emulation of reachabilityFence()
.
See the documentation for Reference.reachabilityFence()
and this discussion
in the concurrency-interest mailing list for more information.
# CN.3. Aren’t there classes that have cleaners or override finalize()
not
to free native resources, but merely to return heap objects to some pools, or merely to report
that some heap objects are not returned to some pools? This is an antipattern because of the
tremendous complexity of using cleaners and finalize()
correctly (see the previous two items) and
the negative impact on performance (especially of finalize()
), that might be even larger than the
impact of not returning objects back to some pool and thus slightly increasing the garbage
allocation rate in the application. If the latter issue arises to be any important, it should better
be diagnosed with async-profiler in the
allocation profiling mode (-e alloc) than by registering cleaners or overriding finalize()
.
This advice also applies when pooled objects are direct ByteBuffers or other Java wrappers of native memory chunks. async-profiler -e malloc could be used in such cases to detect direct memory leaks.
# CN.4. If some classes have some state in native memory and are used
actively in concurrent code, or belong to the public API of the project, was it considered making
them thread-safe? As described in CN.2, if objects of such classes are
inadvertently accessed from multiple threads without proper synchronization, memory corruption and
JVM crashes might result. This is why classes in the JDK such as java.util.zip.Deflater
use synchronization internally despite Deflater
objects are not intended to be used concurrently
from multiple threads.
Note that making classes with some state in native memory thread-safe also implies that the native
state should be safely published in constructors. This means that either the native state should
be stored exclusively in final
fields, or VarHandle.storeStoreFence()
should be called in constructors after full initialization of the native state. If the project
targets JDK 9 and VarHandle
is not available, the same effect could be achieved by wrapping
constructors’ bodies in synchronized (this) { ... }
.
# Bonus: is forbidden-apis configured for the project and are
java.util.StringBuffer
, java.util.Random
and Math.random()
prohibited? StringBuffer
and
Random
are thread-safe and all their methods are synchronized, which is never useful in practice
and only inhibits the performance. In OpenJDK, Math.random()
delegates to a global static Random
instance. StringBuilder
should be used instead of StringBuffer
, ThreadLocalRandom
or
SplittableRandom
should be used instead of Random
(see also T.2).
Reading List
- [JLS] Java Language Specification, Memory Model and
final
field semantics. - [EJ] "Effective Java" by Joshua Bloch, Chapter 11. Concurrency.
- [JCIP] "Java Concurrency in Practice" by Brian Goetz, Tim Peierls, Joshua Bloch, Joseph Bowbeer, David Holmes, and Doug Lea.
- Posts by Aleksey Shipilёv:
- When to use parallel streams written by Doug Lea, with the help of Brian Goetz, Paul Sandoz, Aleksey Shipilev, Heinz Kabutz, Joe Bowbeer, …
- SEI CERT Oracle Coding Standard for Java:
Concurrency checklists for other programming langugages
- C++: Concurrency and parallelism section in C++ Core Guidelines.
- Go: Concurrency section in Effective Go.
Authors
This checklist was originally published as a post on Medium.
The following people contributed ideas and comments about this checklist before it was imported to Github:
- Roman Leventov
- Marko Topolnik
- Matko Medenjak
- Chris Vest
- Simon Willnauer
- Ben Manes
- Gleb Smirnov
- Andrey Satarin
- Benedict Jin
- Petr Janeček
The ideas for some items are taken from "Java Concurrency Gotchas" presentation by Alex Miller and What is the most frequent concurrency issue you've encountered in Java? question on StackOverflow (thanks to Alex Miller who created this question and the contributors).
At the moment when this checklist was imported to Github, all text was written by Roman Leventov.
The checklist is not considered complete, comments and contributions are welcome!
No Copyright
This checklist is public domain. By submitting a PR to this repository contributors agree to release their writing to public domain.
More Resourcesto explore the angular.
mail [email protected] to add your project or resources here 🔥.
- 1Quasar
http://docs.paralleluniverse.co/quasar/
Quasar is a JVM library that provides true lightweight threads, CSP channels and actors.
- 2A big, fast and persistent queue based on memory mapped file.
https://github.com/bulldog2011/bigqueue
A big, fast and persistent queue based on memory mapped file. - bulldog2011/bigqueue
- 3Gradle Build Tool
https://gradle.org
Accelerate developer productivity. Gradle helps teams build, automate and deliver better software, faster.
- 4Union, intersection, and set cardinality in loglog space
https://github.com/LiveRamp/HyperMinHash-java
Union, intersection, and set cardinality in loglog space - LiveRamp/HyperMinHash-java
- 5JayWire Dependency Injection
https://github.com/vanillasource/jaywire
JayWire Dependency Injection. Contribute to vanillasource/jaywire development by creating an account on GitHub.
- 6cglib - Byte Code Generation Library is high level API to generate and transform Java byte code. It is used by AOP, testing, data access frameworks to generate dynamic proxy objects and intercept field access.
https://github.com/cglib/cglib
cglib - Byte Code Generation Library is high level API to generate and transform Java byte code. It is used by AOP, testing, data access frameworks to generate dynamic proxy objects and intercept f...
- 7Java bytecode engineering toolkit
https://github.com/jboss-javassist/javassist
Java bytecode engineering toolkit. Contribute to jboss-javassist/javassist development by creating an account on GitHub.
- 8*old repository* --> this is now integrated in https://github.com/javaparser/javaparser
https://github.com/javaparser/javasymbolsolver
*old repository* --> this is now integrated in https://github.com/javaparser/javaparser - javaparser/javasymbolsolver
- 9Replicate your Key Value Store across your network, with consistency, persistance and performance.
https://github.com/OpenHFT/Chronicle-Map
Replicate your Key Value Store across your network, with consistency, persistance and performance. - OpenHFT/Chronicle-Map
- 10adt4j - Algebraic Data Types for Java
https://github.com/sviperll/adt4j
adt4j - Algebraic Data Types for Java. Contribute to sviperll/adt4j development by creating an account on GitHub.
- 11Advanced date, time and interval library for Java with sun/moon-astronomy and calendars like Chinese, Coptic, Ethiopian, French Republican, Hebrew, Hijri, Historic Christian, Indian National, Japanese, Julian, Korean, Minguo, Persian, Thai, Vietnamese
https://github.com/MenoData/Time4J
Advanced date, time and interval library for Java with sun/moon-astronomy and calendars like Chinese, Coptic, Ethiopian, French Republican, Hebrew, Hijri, Historic Christian, Indian National, Japan...
- 12Use the MongoDB query language to query your relational database, typically from frontend.
https://github.com/mhewedy/spring-data-jpa-mongodb-expressions
Use the MongoDB query language to query your relational database, typically from frontend. - mhewedy/spring-data-jpa-mongodb-expressions
- 13Checkstyle is a development tool to help programmers write Java code that adheres to a coding standard. By default it supports the Google Java Style Guide and Sun Code Conventions, but is highly configurable. It can be invoked with an ANT task and a command line program.
https://github.com/checkstyle/checkstyle
Checkstyle is a development tool to help programmers write Java code that adheres to a coding standard. By default it supports the Google Java Style Guide and Sun Code Conventions, but is highly co...
- 14requery - modern SQL based query & persistence for Java / Kotlin / Android
https://github.com/requery/requery
requery - modern SQL based query & persistence for Java / Kotlin / Android - requery/requery
- 15Binary Artifact Management Tool
https://github.com/artipie/artipie
Binary Artifact Management Tool. Contribute to artipie/artipie development by creating an account on GitHub.
- 16JLine is a Java library for handling console input.
https://github.com/jline/jline3
JLine is a Java library for handling console input. - jline/jline3
- 17JPF is an extensible software analysis framework for Java bytecode. jpf-core is the basis for all JPF projects; you always need to install it. It contains the basic VM and model checking infrastructure, and can be used to check for concurrency defects like deadlocks, and unhandled exceptions like NullPointerExceptions and AssertionErrors.
https://github.com/javapathfinder/jpf-core
JPF is an extensible software analysis framework for Java bytecode. jpf-core is the basis for all JPF projects; you always need to install it. It contains the basic VM and model checking infrastruc...
- 18Manifold is a Java compiler plugin, its features include Metaprogramming, Properties, Extension Methods, Operator Overloading, Templates, a Preprocessor, and more.
https://github.com/manifold-systems/manifold
Manifold is a Java compiler plugin, its features include Metaprogramming, Properties, Extension Methods, Operator Overloading, Templates, a Preprocessor, and more. - manifold-systems/manifold
- 19A collection of source code generators for Java.
https://github.com/google/auto
A collection of source code generators for Java. Contribute to google/auto development by creating an account on GitHub.
- 20Record builder generator for Java records
https://github.com/Randgalt/record-builder
Record builder generator for Java records. Contribute to Randgalt/record-builder development by creating an account on GitHub.
- 21Realm is a mobile database: a replacement for SQLite & ORMs
https://github.com/realm/realm-java
Realm is a mobile database: a replacement for SQLite & ORMs - realm/realm-java
- 22Resilience4j is a fault tolerance library designed for Java8 and functional programming
https://github.com/resilience4j/resilience4j
Resilience4j is a fault tolerance library designed for Java8 and functional programming - resilience4j/resilience4j
- 23Governator is a library of extensions and utilities that enhance Google Guice to provide: classpath scanning and automatic binding, lifecycle management, configuration to field mapping, field validation and parallelized object warmup.
https://github.com/Netflix/governator
Governator is a library of extensions and utilities that enhance Google Guice to provide: classpath scanning and automatic binding, lifecycle management, configuration to field mapping, field valid...
- 24An annotation processor for generating type-safe bean mappers
https://github.com/mapstruct/mapstruct
An annotation processor for generating type-safe bean mappers - mapstruct/mapstruct
- 25Protocol Buffers - Google's data interchange format
https://github.com/protocolbuffers/protobuf
Protocol Buffers - Google's data interchange format - protocolbuffers/protobuf
- 26Java library for the Stripe API.
https://github.com/stripe/stripe-java
Java library for the Stripe API. . Contribute to stripe/stripe-java development by creating an account on GitHub.
- 27SneakyThrow is a Java library to ignore checked exceptions
https://github.com/rainerhahnekamp/sneakythrow
SneakyThrow is a Java library to ignore checked exceptions - rainerhahnekamp/sneakythrow
- 28paritytrading/parity
https://github.com/paritytrading/parity
Contribute to paritytrading/parity development by creating an account on GitHub.
- 29Jollyday - A holiday API
https://github.com/svendiedrichsen/jollyday
Jollyday - A holiday API. Contribute to svendiedrichsen/jollyday development by creating an account on GitHub.
- 30Java binding for etcd
https://github.com/justinsb/jetcd
Java binding for etcd. Contribute to justinsb/jetcd development by creating an account on GitHub.
- 31A Java library for technical analysis.
https://github.com/ta4j/ta4j
A Java library for technical analysis. Contribute to ta4j/ta4j development by creating an account on GitHub.
- 32CSV library for Java that is fast, RFC-compliant and dependency-free.
https://github.com/osiegmar/FastCSV
CSV library for Java that is fast, RFC-compliant and dependency-free. - osiegmar/FastCSV
- 33Simpler, better and faster Java bean mapping framework
https://github.com/orika-mapper/orika
Simpler, better and faster Java bean mapping framework - orika-mapper/orika
- 34LINQ-style queries for Java 8
https://github.com/my2iu/Jinq
LINQ-style queries for Java 8. Contribute to my2iu/Jinq development by creating an account on GitHub.
- 35Guice (pronounced 'juice') is a lightweight dependency injection framework for Java 11 and above, brought to you by Google.
https://github.com/google/guice
Guice (pronounced 'juice') is a lightweight dependency injection framework for Java 11 and above, brought to you by Google. - google/guice
- 36Build JPA Criteria queries using a Stream-like API
https://github.com/querystream/querystream
Build JPA Criteria queries using a Stream-like API - querystream/querystream
- 37Elegance, high performance and robustness all in one java bean mapper
https://github.com/jmapper-framework/jmapper-core
Elegance, high performance and robustness all in one java bean mapper - jmapper-framework/jmapper-core
- 38Reflectionless command line parser
https://github.com/jbock-java/jbock
Reflectionless command line parser. Contribute to jbock-java/jbock development by creating an account on GitHub.
- 39Simple, efficient Excel to POJO library for Java
https://github.com/creditdatamw/zerocell
Simple, efficient Excel to POJO library for Java . Contribute to creditdatamw/zerocell development by creating an account on GitHub.
- 40Catch common Java mistakes as compile-time errors
https://github.com/google/error-prone
Catch common Java mistakes as compile-time errors. Contribute to google/error-prone development by creating an account on GitHub.
- 41JHipster is a development platform to quickly generate, develop, & deploy modern web applications & microservice architectures.
https://github.com/jhipster/generator-jhipster
JHipster is a development platform to quickly generate, develop, & deploy modern web applications & microservice architectures. - jhipster/generator-jhipster
- 42A library for creating interactive console applications in Java
https://github.com/beryx/text-io
A library for creating interactive console applications in Java - beryx/text-io
- 43A high performance caching library for Java
https://github.com/ben-manes/caffeine
A high performance caching library for Java. Contribute to ben-manes/caffeine development by creating an account on GitHub.
- 44KickAss Configuration. An annotation-based configuration system for Java and Kotlin
https://github.com/mariomac/kaconf
KickAss Configuration. An annotation-based configuration system for Java and Kotlin - mariomac/kaconf
- 45A lightning fast, transactional, file-based FIFO for Android and Java.
https://github.com/square/tape
A lightning fast, transactional, file-based FIFO for Android and Java. - square/tape
- 46Redisson - Easy Redis Java client and Real-Time Data Platform. Valkey compatible. Sync/Async/RxJava/Reactive API. Over 50 Redis based Java objects and services: Set, Multimap, SortedSet, Map, List, Queue, Deque, Semaphore, Lock, AtomicLong, Map Reduce, Bloom filter, Spring Cache, Tomcat, Scheduler, JCache API, Hibernate, RPC, local cache ...
https://github.com/redisson/redisson
Redisson - Easy Redis Java client and Real-Time Data Platform. Valkey compatible. Sync/Async/RxJava/Reactive API. Over 50 Redis based Java objects and services: Set, Multimap, SortedSet, Map, List,...
- 47configuration library for JVM languages using HOCON files
https://github.com/lightbend/config
configuration library for JVM languages using HOCON files - lightbend/config
- 48Mixin is a trait/mixin and bytecode weaving framework for Java using ASM
https://github.com/SpongePowered/Mixin
Mixin is a trait/mixin and bytecode weaving framework for Java using ASM - SpongePowered/Mixin
- 49Lightweight dependency injection for Java and Android (JSR-330)
https://github.com/zsoltherpai/feather
Lightweight dependency injection for Java and Android (JSR-330) - zsoltherpai/feather
- 50Build software better, together
https://github.com/xzripper/Void2D
GitHub is where people build software. More than 100 million people use GitHub to discover, fork, and contribute to over 420 million projects.
- 51Elasticsearch Java Rest Client.
https://github.com/searchbox-io/Jest
Elasticsearch Java Rest Client. Contribute to searchbox-io/Jest development by creating an account on GitHub.
- 52:package: Gradle/Maven plugin to package Java applications as native Windows, MacOS, or Linux executables and create installers for them.
https://github.com/fvarrui/JavaPackager
:package: Gradle/Maven plugin to package Java applications as native Windows, MacOS, or Linux executables and create installers for them. - fvarrui/JavaPackager
- 53QuestDB is an open source time-series database for fast ingest and SQL queries
https://github.com/questdb/questdb
QuestDB is an open source time-series database for fast ingest and SQL queries - questdb/questdb
- 54Autumn Lamonte / jexer · GitLab
https://gitlab.com/AutumnMeowMeow/jexer
Java Text User Interface
- 55Extension module to properly support datatypes of javax.money
https://github.com/zalando/jackson-datatype-money
Extension module to properly support datatypes of javax.money - zalando/jackson-datatype-money
- 56The fast, Open Source and easy-to-use solver
https://www.optaplanner.org
Solve any constraint optimization problem easily, including the Vehicle Routing Problem, Employee Rostering, Maintenance Scheduling and many others.
- 57Parquet
https://parquet.apache.org
The Apache Parquet Website
- 58Debezium
https://debezium.io/
Debezium is an open source distributed platform for change data capture. Start it up, point it at your databases, and your apps can start responding to all of the inserts, updates, and deletes that other apps commit to your databases. Debezium is durable and fast, so your apps can respond quickly and never miss an event, even when things go wrong.
- 59Distributed SQL query engine for big data
https://trino.io
Trino is a high performance, distributed SQL query engine for big data.
- 60The easiest way to write SQL in Java
https://www.jooq.org
jOOQ, a fluent API for typesafe SQL query construction and execution.
- 61The Community for Open Collaboration and Innovation | The Eclipse Foundation
https://www.eclipse.org
The Eclipse Foundation provides our global community of individuals and organisations with a mature, scalable, and business-friendly environment for open source …
- 62The Standard Widget Toolkit | The Eclipse Foundation
https://www.eclipse.org/swt/
The Eclipse Foundation - home to a global community, the Eclipse IDE, Jakarta EE and over 415 open source projects, including runtimes, tools and frameworks.
- 63Massoni - JmlOk2
https://massoni.computacao.ufcg.edu.br/home/jmlok
A tool for detect and categorize nonconformances in Contract-Based Programs What is JmlOk2? JmlOk2 is a tool that detects nonconformances between Java code and JML specification through the feedback-directed random tests generation. Also, JmlOk2 is a tool that suggests likely causes for
- 64LITIENGINE 🎮 Free and Open Source Java 2D Game Engine
https://litiengine.com/
LITIENGINE is the pure 2D Java Game Engine and it's entirely free. 2D Sound ✓ 2D Physics ✓ 2D Render Engine ✓ Start Now and build your video game ►
- 65IntelliJ IDEA – the Leading Java and Kotlin IDE
https://www.jetbrains.com/idea/
IntelliJ IDEA is undoubtedly the top-choice IDE for software developers. It makes Java and Kotlin development a more productive and enjoyable experience.
- 66Java in Visual Studio Code
https://code.visualstudio.com/docs/languages/java
Learn about Visual Studio Code editor features (code completion, debugging, snippets, linting) for Java.
- 67Scene Builder - Gluon
https://gluonhq.com/products/scene-builder/
Drag & Drop,Rapid Application Development. Download Now Integrated Scene Builder works with the JavaFX ecosystem – official controls, community projects, and Gluon offerings including Gluon Mobile, Gluon Desktop, and Gluon CloudLink. Simple Drag & Drop user interface design allows for rapid iteration. Separation of design and logic files allows for team members to quickly and […]
- 68jQAssistant
https://jqassistant.org
jQAssistant has 5 repositories available. Follow their code on GitHub.
- 69A project to cause (controlled) destruction on your jvm application
https://github.com/nicolasmanic/perses
A project to cause (controlled) destruction on your jvm application - GitHub - nick-kanakis/perses: A project to cause (controlled) destruction on your jvm application
- 70Redis Java client
https://github.com/xetorthio/jedis
Redis Java client. Contribute to redis/jedis development by creating an account on GitHub.
- 71Selma Java bean mapping that compiles
https://github.com/xebia-france/selma
Selma Java bean mapping that compiles. Contribute to publicissapient-france/selma development by creating an account on GitHub.
- 72Fault tolerance and resilience patterns for the JVM
https://github.com/jhalterman/failsafe
Fault tolerance and resilience patterns for the JVM - failsafe-lib/failsafe
- 73JTA Transaction Manager
https://github.com/bitronix/btm
JTA Transaction Manager. Contribute to scalar-labs/btm development by creating an account on GitHub.
- 74Get rid of the boilerplate code in properties based configuration.
https://github.com/lviggiano/owner
Get rid of the boilerplate code in properties based configuration. - matteobaccan/owner
- 75dOOv (Domain Object Oriented Validation) a fluent API for type-safe bean validation and mapping
https://github.com/doov-io/doov
dOOv (Domain Object Oriented Validation) a fluent API for type-safe bean validation and mapping - doov-org/doov
- 76Identifies and prioritizes God Classes and Highly Coupled classes in Java codebases you should refactor first.
https://github.com/jimbethancourt/RefactorFirst
Identifies and prioritizes God Classes and Highly Coupled classes in Java codebases you should refactor first. - refactorfirst/RefactorFirst
- 77A streaming JsonPath processor in Java
https://github.com/jsurfer/JsonSurfer
A streaming JsonPath processor in Java. Contribute to wanglingsong/JsonSurfer development by creating an account on GitHub.
- 78:fire: Seata is an easy-to-use, high-performance, open source distributed transaction solution.
https://github.com/seata/seata
:fire: Seata is an easy-to-use, high-performance, open source distributed transaction solution. - apache/incubator-seata
- 79ImageJ
https://imagej.net/ImageJ
The ImageJ wiki is a community-edited knowledge base on topics relating to ImageJ, a public domain program for processing and analyzing scientific images, and its ecosystem of derivatives and variants, including ImageJ2, Fiji, and others.
- 80Internet Calendaring and Scheduling Core Object Specification (iCalendar)
https://tools.ietf.org/html/rfc5545
This document defines the iCalendar data format for representing and exchanging calendaring and scheduling information such as events, to-dos, journal entries, and free/busy information, independent of any particular calendar service or protocol. [STANDARDS-TRACK]
- 81Welcome to the Narayana community!
https://narayana.io
With over 30 years of expertise in the area of transaction processing, Narayana is the premier open source transaction manager. It has been used extensively within industry and to drive standards including the OMG and Web Services.
- 82The AspectJ Project | The Eclipse Foundation
https://www.eclipse.org/aspectj/
The Eclipse Foundation - home to a global community, the Eclipse IDE, Jakarta EE and over 415 open source projects, including runtimes, tools and frameworks.
- 83Home
https://www.atomikos.com
Distributed transactions without application server, outside of the container - for Java and REST...
- 84Machine Learning in Java
https://tribuo.org/
Tribuo is a Java ML library for multi-class classification, regression, clustering, anomaly detection and multi-label classification.
- 85Elastic — The Search AI Company
https://www.elastic.co
Power insights and outcomes with The Elastic Search AI Platform. See into your data and find answers that matter with enterprise solutions designed to help you accelerate time to insight. Try Elastic ...
- 86Explore, Visualize, Discover Data | Elastic
https://www.elastic.co/kibana
Download Kibana or the complete Elastic Stack for free and start visualizing, analyzing, and exploring your data with Elastic in minutes....
- 87CodenameOne/vm at master · codenameone/CodenameOne
https://github.com/codenameone/CodenameOne/tree/master/vm
Cross-platform framework for building truly native mobile apps with Java or Kotlin. Write Once Run Anywhere support for iOS, Android, Desktop & Web. - codenameone/CodenameOne
- 88Stream Processing and Complex Event Processing Engine
https://github.com/siddhi-io/siddhi
Stream Processing and Complex Event Processing Engine - siddhi-io/siddhi
- 89Apache Kafka
https://kafka.apache.org
Apache Kafka: A Distributed Streaming Platform.
- 90Quarkus - Supersonic Subatomic Java
https://quarkus.io
Quarkus: Supersonic Subatomic Java
- 91P6Spy is a framework that enables database data to be seamlessly intercepted and logged with no code changes to the application.
https://github.com/p6spy/p6spy
P6Spy is a framework that enables database data to be seamlessly intercepted and logged with no code changes to the application. - p6spy/p6spy
- 92Java Statistical Analysis Tool, a Java library for Machine Learning
https://github.com/EdwardRaff/JSAT
Java Statistical Analysis Tool, a Java library for Machine Learning - GitHub - EdwardRaff/JSAT: Java Statistical Analysis Tool, a Java library for Machine Learning
- 93Collect, Parse, Transform Logs | Elastic
https://www.elastic.co/logstash
Logstash (part of the Elastic Stack) integrates data from any source, in any format with this flexible, open source collection, parsing, and enrichment pipeline. Download for free....
- 94Developer-first error tracking and performance monitoring
https://github.com/getsentry/sentry
Developer-first error tracking and performance monitoring - getsentry/sentry
- 95OACC - Java Application Security Framework
http://oaccframework.org
OACC is a fully featured open-source Java API to both enforce and manage your application's authentication and authorization needs.
- 96RabbitMQ Java client
https://github.com/rabbitmq/rabbitmq-java-client
RabbitMQ Java client. Contribute to rabbitmq/rabbitmq-java-client development by creating an account on GitHub.
- 97Multi-OS Engine
https://multi-os-engine.org
Create iOS Apps in Java Port your existing Android App, or build a native Cross-Platform App from scratch.
- 98hippo4j/README-EN.md at develop · opengoofy/hippo4j
https://github.com/opengoofy/hippo4j/blob/develop/README-EN.md
📌 异步线程池框架,支持线程池动态变更&监控&报警,无需修改代码轻松引入。Asynchronous thread pool framework, support Thread Pool Dynamic Change & monitoring & Alarm, no need to modify the code easily introduced. - ope...
- 99MyBatis SQL mapper framework for Java
https://github.com/mybatis/mybatis-3
MyBatis SQL mapper framework for Java. Contribute to mybatis/mybatis-3 development by creating an account on GitHub.
- 100Detect uses of legacy Java APIs
https://github.com/gaul/modernizer-maven-plugin
Detect uses of legacy Java APIs. Contribute to gaul/modernizer-maven-plugin development by creating an account on GitHub.
- 101svix-webhooks/java at main · svix/svix-webhooks
https://github.com/svix/svix-webhooks/tree/main/java
The enterprise-ready webhooks service 🦀. Contribute to svix/svix-webhooks development by creating an account on GitHub.
- 102Transform ML models into a native code (Java, C, Python, Go, JavaScript, Visual Basic, C#, R, PowerShell, PHP, Dart, Haskell, Ruby, F#, Rust) with zero dependencies
https://github.com/BayesWitnesses/m2cgen
Transform ML models into a native code (Java, C, Python, Go, JavaScript, Visual Basic, C#, R, PowerShell, PHP, Dart, Haskell, Ruby, F#, Rust) with zero dependencies - BayesWitnesses/m2cgen
- 103Microsoft Build of OpenJDK
https://github.com/microsoft/openjdk
Microsoft Build of OpenJDK. Contribute to microsoft/openjdk development by creating an account on GitHub.
- 104Event bus for Android and Java that simplifies communication between Activities, Fragments, Threads, Services, etc. Less code, better quality.
https://github.com/greenrobot/EventBus
Event bus for Android and Java that simplifies communication between Activities, Fragments, Threads, Services, etc. Less code, better quality. - greenrobot/EventBus
- 105The open-source Java obfuscation tool working with Ant and Gradle by yWorks - the diagramming experts
https://github.com/yWorks/yGuard
The open-source Java obfuscation tool working with Ant and Gradle by yWorks - the diagramming experts - yWorks/yGuard
- 106Log analyser / visualiser for Java HotSpot JIT compiler. Inspect inlining decisions, hot methods, bytecode, and assembly. View results in the JavaFX user interface.
https://github.com/AdoptOpenJDK/jitwatch
Log analyser / visualiser for Java HotSpot JIT compiler. Inspect inlining decisions, hot methods, bytecode, and assembly. View results in the JavaFX user interface. - AdoptOpenJDK/jitwatch
- 107Red Hat build of OpenJDK | Red Hat Developer
https://developers.redhat.com/products/openjdk/overview
The Red Hat build of OpenJDK is an open source implementation of the Java Platform, Standard Edition (Java SE).
- 108An in-memory file system for Java 7+
https://github.com/google/jimfs
An in-memory file system for Java 7+. Contribute to google/jimfs development by creating an account on GitHub.
- 109Java client for Consul HTTP API
https://github.com/Ecwid/consul-api
Java client for Consul HTTP API. Contribute to Ecwid/consul-api development by creating an account on GitHub.
- 110jOOX - The Power of jQuery Applied to W3C DOM Like JDBC, DOM is a powerful, yet very verbose low-level API to manipulate XML. The HTML DOM an be manipulated with the popular jQuery product, in JavaScript. Why don't we have jQuery in Java? jOOX is jQuery's XML parts, applied to Java.
https://github.com/jooq/joox
jOOX - The Power of jQuery Applied to W3C DOM Like JDBC, DOM is a powerful, yet very verbose low-level API to manipulate XML. The HTML DOM an be manipulated with the popular jQuery product, in Java...
- 111FizzBuzz Enterprise Edition is a no-nonsense implementation of FizzBuzz made by serious businessmen for serious business purposes.
https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition
FizzBuzz Enterprise Edition is a no-nonsense implementation of FizzBuzz made by serious businessmen for serious business purposes. - EnterpriseQualityCoding/FizzBuzzEnterpriseEdition
- 112An application observability facade for the most popular observability tools. Think SLF4J, but for observability.
https://github.com/micrometer-metrics/micrometer
An application observability facade for the most popular observability tools. Think SLF4J, but for observability. - micrometer-metrics/micrometer
- 113Extract tables from PDF files
https://github.com/tabulapdf/tabula-java
Extract tables from PDF files. Contribute to tabulapdf/tabula-java development by creating an account on GitHub.
- 114OpenPDF is a free Java library for creating and editing PDF files, with a LGPL and MPL open source license. OpenPDF is based on a fork of iText. We welcome contributions from other developers. Please feel free to submit pull-requests and bugreports to this GitHub repository.
https://github.com/LibrePDF/OpenPDF
OpenPDF is a free Java library for creating and editing PDF files, with a LGPL and MPL open source license. OpenPDF is based on a fork of iText. We welcome contributions from other developers. Plea...
- 115JavaMelody : monitoring of JavaEE applications
https://github.com/javamelody/javamelody
JavaMelody : monitoring of JavaEE applications. Contribute to javamelody/javamelody development by creating an account on GitHub.
- 116Java Abstracted Foreign Function Layer
https://github.com/jnr/jnr-ffi
Java Abstracted Foreign Function Layer. Contribute to jnr/jnr-ffi development by creating an account on GitHub.
- 117A lightweight, simple FTP server. Pure Java, no dependencies.
https://github.com/Guichaguri/MinimalFTP
A lightweight, simple FTP server. Pure Java, no dependencies. - Guichaguri/MinimalFTP
- 118TCP/UDP client/server library for Java, based on Kryo
https://github.com/EsotericSoftware/kryonet
TCP/UDP client/server library for Java, based on Kryo - EsotericSoftware/kryonet
- 119XML/XHTML and CSS 2.1 renderer in pure Java
https://github.com/flyingsaucerproject/flyingsaucer
XML/XHTML and CSS 2.1 renderer in pure Java. Contribute to flyingsaucerproject/flyingsaucer development by creating an account on GitHub.
- 120Efficient reliable UDP unicast, UDP multicast, and IPC message transport
https://github.com/real-logic/Aeron
Efficient reliable UDP unicast, UDP multicast, and IPC message transport - real-logic/aeron
- 121Prometheus instrumentation library for JVM applications
https://github.com/prometheus/client_java
Prometheus instrumentation library for JVM applications - prometheus/client_java
- 122JObfuscator — Java Source Code Obfuscation & Protection
https://www.pelock.com/products/jobfuscator
JObfuscator is a source code obfuscator for the Java language. Protect Java source code & algorithms from hacking, cracking, reverse engineering, decompilation & technology theft.
- 123:chart_with_upwards_trend: Capturing JVM- and application-level metrics. So you know what's going on.
https://github.com/dropwizard/metrics
:chart_with_upwards_trend: Capturing JVM- and application-level metrics. So you know what's going on. - dropwizard/metrics
- 124Statistical Machine Intelligence & Learning Engine
https://github.com/haifengl/smile
Statistical Machine Intelligence & Learning Engine - haifengl/smile
- 125PipelinR is a lightweight command processing pipeline ❍ ⇢ ❍ ⇢ ❍ for your Java awesome app.
https://github.com/sizovs/pipelinr
PipelinR is a lightweight command processing pipeline ❍ ⇢ ❍ ⇢ ❍ for your Java awesome app. - GitHub - sizovs/PipelinR: PipelinR is a lightweight command processing pipeline ❍ ⇢ ❍ ⇢ ❍ for your Java...
- 126Home - Micronaut Framework
https://micronaut.io
The Micronaut® framework is a modern, open source, JVM-based, full-stack toolkit for building modular, easily testable microservices and serverless applications.
- 127Java reporting library for creating dynamic report designs at runtime
https://github.com/dynamicreports/dynamicreports
Java reporting library for creating dynamic report designs at runtime - dynamicreports/dynamicreports
- 128Java Structured Logging API for Logback, Log4J2, and JUL
https://github.com/tersesystems/echopraxia
Java Structured Logging API for Logback, Log4J2, and JUL - tersesystems/echopraxia
- 129Support alternative markup for Apache Maven POM files
https://github.com/takari/polyglot-maven
Support alternative markup for Apache Maven POM files - takari/polyglot-maven
- 130Pure Java ZeroMQ
https://github.com/zeromq/jeromq
Pure Java ZeroMQ . Contribute to zeromq/jeromq development by creating an account on GitHub.
- 131OctoLinker — Links together, what belongs together
https://github.com/OctoLinker/OctoLinker
OctoLinker — Links together, what belongs together - OctoLinker/OctoLinker
- 132DataMelt
https://datamelt.org/
Java program for data analysis, statistics and visualization
- 133AWS Service registry for resilient mid-tier load balancing and failover.
https://github.com/Netflix/eureka
AWS Service registry for resilient mid-tier load balancing and failover. - Netflix/eureka
- 134A fast, light and cloud native OAuth 2.0 authorization microservices based on light-4j
https://github.com/networknt/light-oauth2/.
A fast, light and cloud native OAuth 2.0 authorization microservices based on light-4j - networknt/light-oauth2
- 135ISBN core
https://github.com/ladutsko/isbn-core
ISBN core. Contribute to ladutsko/isbn-core development by creating an account on GitHub.
- 136Provides tracing abstractions over tracers and tracing system reporters.
https://github.com/micrometer-metrics/tracing
Provides tracing abstractions over tracers and tracing system reporters. - micrometer-metrics/tracing
- 137Java library for representing, parsing and encoding URNs as in RFC2141 and RFC8141 (Maintained by @claussni)
https://github.com/slub/urnlib
Java library for representing, parsing and encoding URNs as in RFC2141 and RFC8141 (Maintained by @claussni) - slub/urnlib
- 138The Java gRPC implementation. HTTP/2 based RPC
https://github.com/grpc/grpc-java
The Java gRPC implementation. HTTP/2 based RPC. Contribute to grpc/grpc-java development by creating an account on GitHub.
- 139The java implementation of Apache Dubbo. An RPC and microservice framework.
https://github.com/apache/dubbo
The java implementation of Apache Dubbo. An RPC and microservice framework. - apache/dubbo
- 140commons networking utils
https://github.com/CiscoSE/commons-networking
commons networking utils. Contribute to CiscoSE/commons-networking development by creating an account on GitHub.
- 141IP2Location.io Java SDK allows user to query for an enriched data set based on IP address and provides WHOIS lookup api that helps users to obtain domain information.
https://github.com/ip2location/ip2location-io-java
IP2Location.io Java SDK allows user to query for an enriched data set based on IP address and provides WHOIS lookup api that helps users to obtain domain information. - ip2location/ip2location-io-java
- 142OpenAI Api Client in Java
https://github.com/TheoKanning/openai-java
OpenAI Api Client in Java. Contribute to TheoKanning/openai-java development by creating an account on GitHub.
- 143Best-of-breed OpenTracing utilities, instrumentations and extensions
https://github.com/zalando/opentracing-toolbox
Best-of-breed OpenTracing utilities, instrumentations and extensions - zalando/opentracing-toolbox
- 144OpenTelemetry Java SDK
https://github.com/open-telemetry/opentelemetry-java
OpenTelemetry Java SDK. Contribute to open-telemetry/opentelemetry-java development by creating an account on GitHub.
- 145Elide
https://elide.io
Model Driven Json API and GraphQL Web Services for Java
- 146The official AWS SDK for Java - Version 2
https://github.com/aws/aws-sdk-java-v2
The official AWS SDK for Java - Version 2. Contribute to aws/aws-sdk-java-v2 development by creating an account on GitHub.
- 147🛑 This library is DEPRECATED!
https://github.com/jaegertracing/jaeger-client-java
🛑 This library is DEPRECATED! Contribute to jaegertracing/jaeger-client-java development by creating an account on GitHub.
- 148an open source solution to application performance monitoring for java server applications
https://github.com/stagemonitor/stagemonitor
an open source solution to application performance monitoring for java server applications - stagemonitor/stagemonitor
- 149A Sentry SDK for Java, Android and other JVM languages.
https://github.com/getsentry/sentry-java
A Sentry SDK for Java, Android and other JVM languages. - getsentry/sentry-java
- 150A powerful flow control component enabling reliability, resilience and monitoring for microservices. (面向云原生微服务的高可用流控防护组件)
https://github.com/alibaba/Sentinel
A powerful flow control component enabling reliability, resilience and monitoring for microservices. (面向云原生微服务的高可用流控防护组件) - alibaba/Sentinel
- 151Your relational data. Objectively. - Hibernate ORM
http://hibernate.org/orm/
Idiomatic persistence for Java and relational databases.
- 152A networking framework that evolves with your application
https://github.com/apple/servicetalk
A networking framework that evolves with your application - apple/servicetalk
- 153Ultra-fast SQL-like queries on Java collections
https://github.com/npgall/cqengine
Ultra-fast SQL-like queries on Java collections. Contribute to npgall/cqengine development by creating an account on GitHub.
- 154Home | MobileUI
https://mobileui.dev
MobileUI Framework for cross-platform app development with Kotlin and Java.
- 155Cryptomator - Free Cloud Encryption for Dropbox & Co
https://cryptomator.org
Encrypt Dropbox, Google Drive, and any other cloud. Cryptomator is free and open source.
- 156GraphStream - A Dynamic Graph Library
http://graphstream-project.org
GraphStream, java library, API, Graph Visualisation, Graph Layout
- 157Cloud Application Platform | Heroku
https://www.heroku.com
Heroku is a platform as a service (PaaS) that enables developers to build, run, and operate applications entirely in the cloud.
- 158ActiveJ RPC | Lightning-fast binary protocol for high-load architecture | ActiveJ 6.0
https://rpc.activej.io
ActiveJ RPC is a lightning-fast binary protocol for high-load microservices architecture
- 159Build software better, together
https://github.com/DaveJarvis/KeenType
GitHub is where people build software. More than 100 million people use GitHub to discover, fork, and contribute to over 420 million projects.
- 160Topaz | Topaz
https://www.topaz.sh
An open-source, self-hosted, fine-grained access control service for Cloud Native applications
- 161GraalVM compiles Java applications into native executables that start instantly, scale fast, and use fewer compute resources 🚀
https://github.com/oracle/graal
GraalVM compiles Java applications into native executables that start instantly, scale fast, and use fewer compute resources 🚀 - oracle/graal
- 162Password strength estimator
https://github.com/GoSimpleLLC/nbvcxz
Password strength estimator. Contribute to GoSimpleLLC/nbvcxz development by creating an account on GitHub.
- 163Red Hat OpenShift enterprise application platform
https://www.openshift.com
Red Hat® OpenShift® is a comprehensive application platform to build, modernize, and deploy applications, including AI-enabled apps, at scale.
- 164jmix.io
https://www.cuba-platform.com/
Jmix is a general-purpose high productivity software development platform for building line-of-business applications powered by a professional development environment IntelliJ IDEA and focused on implementing advanced business logic compared to Low Code and BPM platforms.
- 165Eclipse Deeplearning4j
https://deeplearning4j.org
The Eclipse Deeplearning4j Project. Eclipse Deeplearning4j has 4 repositories available. Follow their code on GitHub.
- 166Cross-Platform App Development with Java/Kotlin
https://www.codenameone.com
Open-source cross-platform mobile app development framework to build native iOS, Android, Desktop & Web apps with a single Java or Kotlin codebase.
- 167Alibaba Dragonwell8 JDK
https://github.com/alibaba/dragonwell8
Alibaba Dragonwell8 JDK. Contribute to dragonwell-project/dragonwell8 development by creating an account on GitHub.
- 168Integrate with the latest language models, image generation, speech, and deep learning frameworks like ChatGPT, DALL·E, and Cohere using few java lines.
https://github.com/Barqawiz/IntelliJava
Integrate with the latest language models, image generation, speech, and deep learning frameworks like ChatGPT, DALL·E, and Cohere using few java lines. - intelligentnode/IntelliJava
- 169Apache Pulsar | Apache Pulsar
https://pulsar.apache.org
Apache Pulsar is an open-source, distributed messaging and streaming platform built for the cloud.
- 170Eclipse OpenJ9: A Java Virtual Machine for OpenJDK that's optimized for small footprint, fast start-up, and high throughput. Builds on Eclipse OMR (https://github.com/eclipse/omr) and combines with the Extensions for OpenJDK for OpenJ9 repo.
https://github.com/eclipse/openj9
Eclipse OpenJ9: A Java Virtual Machine for OpenJDK that's optimized for small footprint, fast start-up, and high throughput. Builds on Eclipse OMR (https://github.com/eclipse/omr) and combine...
- 171Tink is a multi-language, cross-platform, open source library that provides cryptographic APIs that are secure, easy to use correctly, and hard(er) to misuse.
https://github.com/google/tink
Tink is a multi-language, cross-platform, open source library that provides cryptographic APIs that are secure, easy to use correctly, and hard(er) to misuse. - tink-crypto/tink
- 172APM, (Application Performance Management) tool for large-scale distributed systems.
https://github.com/naver/pinpoint
APM, (Application Performance Management) tool for large-scale distributed systems. - GitHub - pinpoint-apm/pinpoint: APM, (Application Performance Management) tool for large-scale distributed sys...
- 173Java wrapper for the popular chat & VOIP service: Discord https://discord.com
https://github.com/DV8FromTheWorld/JDA
Java wrapper for the popular chat & VOIP service: Discord https://discord.com - discord-jda/JDA
- 174Home - ISA-Ali
http://alias-i.com/lingpipe/
The School’s goals and methods are strikingly different from many short-term computer courses. Teaching programming is not reduced to listing and mindlessly memorizing language statements, which eventually the student does not know how to apply to the solution of a particular problem.
- 175API gateway for REST, OpenAPI, GraphQL and SOAP written in Java.
https://github.com/membrane/service-proxy
API gateway for REST, OpenAPI, GraphQL and SOAP written in Java. - membrane/api-gateway
- 176AutoMQ is a cloud-first alternative to Kafka by decoupling durability to S3 and EBS. 10x cost-effective. Autoscale in seconds. Single-digit ms latency.
https://github.com/AutoMQ/automq-for-kafka
AutoMQ is a cloud-first alternative to Kafka by decoupling durability to S3 and EBS. 10x cost-effective. Autoscale in seconds. Single-digit ms latency. - AutoMQ/automq
- 177A scientific charting library focused on performance optimised real-time data visualisation at 25 Hz update rates for data sets with a few 10 thousand up to 5 million data points.
https://github.com/GSI-CS-CO/chart-fx
A scientific charting library focused on performance optimised real-time data visualisation at 25 Hz update rates for data sets with a few 10 thousand up to 5 million data points. - fair-acc/chart-fx
- 178A blazingly fast multi-language serialization framework powered by JIT and zero-copy.
https://github.com/alipay/fury
A blazingly fast multi-language serialization framework powered by JIT and zero-copy. - apache/fury
- 179Home
https://www.graylog.org
Graylog is a leading centralized log management solution for capturing, storing, and enabling real-time analysis of terabytes of machine data.
- 180Apache HertzBeat(incubating) is a real-time monitoring system with agentless, performance cluster, prometheus-compatible, custom monitoring and status page building capabilities.
https://github.com/dromara/hertzbeat
Apache HertzBeat(incubating) is a real-time monitoring system with agentless, performance cluster, prometheus-compatible, custom monitoring and status page building capabilities. - apache/hertzbeat
- 181Cloud Computing Services | Google Cloud
https://cloud.google.com
Meet your business challenges head on with cloud computing services from Google, including data management, hybrid & multi-cloud, and AI & ML.
- 182Test Automation Made Simple
https://github.com/intuit/karate
Test Automation Made Simple. Contribute to karatelabs/karate development by creating an account on GitHub.
- 183MockServer
https://www.mock-server.com
MockServer enables easy mocking of any system you integrate with via HTTP or HTTPS. It also proxies, allowing introspection and modification of proxied traffic, with all proxy protocols (i.e. port forwarding, HTTP, HTTPS, SOCKS4, SOCKS5, etc).
- 184Javalin - A lightweight Java and Kotlin web framework. Create REST APIs in Java or Kotlin easily.
https://javalin.io/
Javalin - A lightweight Java and Kotlin web framework. Create REST APIs in Java or Kotlin easily.
- 185ActiveJ | Alternative Java platform for web, high load, and cloud programming | ActiveJ 6.0
https://activej.io
ActiveJ is an alternative Java platform built from the ground up for web, high load, and cloud programming as a replacement for Spring, Quarkus, Vert.x and other sub-optimal solutions
- 186JGit | The Eclipse Foundation
https://www.eclipse.org/jgit/
The Eclipse Foundation - home to a global community, the Eclipse IDE, Jakarta EE and over 415 open source projects, including runtimes, tools and frameworks.
- 187Awesome Java | LibHunt
https://java.libhunt.com
Your go-to Java Toolbox. A curated list of awesome Java frameworks, libraries and software. 1050 projects organized into 134 categories.
- 188PrimeFaces
https://www.primefaces.org
Ultimate UI Framework
- 189Head First Java, 3rd Edition
https://www.oreilly.com/library/view/head-first-java/9781492091646/
What will you learn from this book? Head First Java is a complete learning experience in Java and object-oriented programming. With this book, you'll learn the Java language with a … - Selection from Head First Java, 3rd Edition [Book]
- 190WireMock - flexible, open source API mocking
http://wiremock.org
WireMock is a tool for building mock APIs. API mocking enables you build stable, predictable development environments when the APIs you depend on are unreliable or don’t exist.
- 191Java, SQL and jOOQ.
https://blog.jooq.org
Oracle 23ai still doesn't support the standard SQL FILTER clause on aggregate functions, which can prove to be tricky to emulate on JSON aggregate functions
- 192Roadmap to becoming a Java developer in 2024
https://github.com/s4kibs4mi/java-developer-roadmap
Roadmap to becoming a Java developer in 2024. Contribute to s4kibs4mi/java-developer-roadmap development by creating an account on GitHub.
- 193The SDKMAN! Command Line Interface
https://github.com/sdkman/sdkman-cli
The SDKMAN! Command Line Interface. Contribute to sdkman/sdkman-cli development by creating an account on GitHub.
- 194Java regular expressions made easy.
https://github.com/VerbalExpressions/JavaVerbalExpressions
Java regular expressions made easy. Contribute to VerbalExpressions/JavaVerbalExpressions development by creating an account on GitHub.
- 195Load testing designed for DevOps and CI/CD | Gatling
https://gatling.io
Gatling is a load testing tool for web applications designed for DevOps and Continuous Integration. Try Gatling now!
- 196(cross-platform) Java Version Manager
https://github.com/shyiko/jabba
(cross-platform) Java Version Manager. Contribute to shyiko/jabba development by creating an account on GitHub.
- 197Easy Setup Stub Server
https://github.com/dreamhead/moco
Easy Setup Stub Server. Contribute to dreamhead/moco development by creating an account on GitHub.
- 198Object-Oriented Java primitives, as an alternative to Google Guava and Apache Commons
https://github.com/yegor256/cactoos
Object-Oriented Java primitives, as an alternative to Google Guava and Apache Commons - yegor256/cactoos
- 199foojay – a place for friends of OpenJDK
https://foojay.io/today/category/podcast/
foojay is a place for friends of OpenJDK, a one stop shop for all things Java. Learn More.
- 200Build Modern Web Apps using Java Full-Stack platform
https://vaadin.com
Vaadin is a full-stack platform for building responsive, modern web applications in Java with a library of UI components and powerful development tools.
- 201Newest 'java' Questions
https://stackoverflow.com/questions/tagged/java
Stack Overflow | The World’s Largest Online Community for Developers
- 202The Well-Grounded Java Developer, Second Edition
https://www.manning.com/books/the-well-grounded-java-developer-second-edition
Understanding Java from the JVM up gives you a solid foundation to grow your expertise and take on advanced techniques for performance, concurrency, containerization, and more.</b><br/><br/> In The Well-Grounded Java Developer, Second Edition</i> you will learn: The new Java module system and why you should use it</li> Bytecode for the JVM, including operations and classloading</li> Performance tuning the JVM</li> Working with Java’s built-in concurrency and expanded options</li> Programming in Kotlin and Clojure on the JVM</li> Maximizing the benefits from your build/CI tooling with Maven and Gradle</li> Running the JVM in containers</li> Planning for future JVM releases</li> </ul> The Well-Grounded Java Developer, Second Edition</i> introduces both the modern innovations and timeless fundamentals you need to know to become a Java master. Authors Ben Evans, Martijn Verburg, and Jason Clark distill their decades of experience as Java Champions, veteran developers, and key contributors to the Java ecosystem into this clear and practical guide. You’ll discover how Java works under the hood and learn design secrets from Java’s long history. Each concept is illustrated with hands-on examples, including a fully modularized application/library and creating your own multithreaded application.
- 203A curated list of resources related to the Java annotation processing API (JSR 269)
https://github.com/gunnarmorling/awesome-annotation-processing
A curated list of resources related to the Java annotation processing API (JSR 269) - gunnarmorling/awesome-annotation-processing
- 204MinIO Client SDK for Java
https://github.com/minio/minio-java
MinIO Client SDK for Java. Contribute to minio/minio-java development by creating an account on GitHub.
- 205Snapshot testing for Java, Kotlin, and the JVM
https://github.com/diffplug/selfie
Snapshot testing for Java, Kotlin, and the JVM. Contribute to diffplug/selfie development by creating an account on GitHub.
- 206Google core libraries for Java
https://github.com/google/guava
Google core libraries for Java. Contribute to google/guava development by creating an account on GitHub.
- 207PowerMock is a Java framework that allows you to unit test code normally regarded as untestable.
https://github.com/powermock/powermock
PowerMock is a Java framework that allows you to unit test code normally regarded as untestable. - powermock/powermock
- 208🎯 ConsoleCaptor captures console output for unit and integration testing purposes
https://github.com/Hakky54/console-captor
🎯 ConsoleCaptor captures console output for unit and integration testing purposes - Hakky54/console-captor
- 209A TestNG like dataprovider runner for JUnit with many additional features
https://github.com/TNG/junit-dataprovider
A TestNG like dataprovider runner for JUnit with many additional features - TNG/junit-dataprovider
- 210A curated list of awesome Gradle plugins and resources for a better development workflow automation.
https://github.com/ksoichiro/awesome-gradle
A curated list of awesome Gradle plugins and resources for a better development workflow automation. - ksoichiro/awesome-gradle
- 211A curated list of delightful Selenium resources.
https://github.com/christian-bromann/awesome-selenium
A curated list of delightful Selenium resources. Contribute to christian-bromann/awesome-selenium development by creating an account on GitHub.
- 212Dex : The Data Explorer -- A data visualization tool written in Java/Groovy/JavaFX capable of powerful ETL and publishing web visualizations.
https://github.com/PatMartin/Dex
Dex : The Data Explorer -- A data visualization tool written in Java/Groovy/JavaFX capable of powerful ETL and publishing web visualizations. - PatMartin/Dex
- 213Java lib for monitoring directories or individual files via java.nio.file.WatchService
https://github.com/vorburger/ch.vorburger.fswatch
Java lib for monitoring directories or individual files via java.nio.file.WatchService - vorburger/ch.vorburger.fswatch
- 214A collaborative list of great resources about RESTful API architecture, development, test, and performance
https://github.com/marmelab/awesome-rest
A collaborative list of great resources about RESTful API architecture, development, test, and performance - marmelab/awesome-rest
- 215EasyMock, makes mocking easier since 2001
https://github.com/easymock/easymock
EasyMock, makes mocking easier since 2001. Contribute to easymock/easymock development by creating an account on GitHub.
- 216Test if a request/response matches a given raml definition
https://github.com/nidi3/raml-tester
Test if a request/response matches a given raml definition - nidi3/raml-tester
- 217dregex is a Java library that implements a regular expression engine using deterministic finite automata (DFA). It supports some Perl-style features and yet retains linear matching time, and also offers set operations.
https://github.com/marianobarrios/dregex
dregex is a Java library that implements a regular expression engine using deterministic finite automata (DFA). It supports some Perl-style features and yet retains linear matching time, and also o...
- 218Java scope functions inspired by Kotlin
https://github.com/evpl/jkscope
Java scope functions inspired by Kotlin. Contribute to evpl/jkscope development by creating an account on GitHub.
- 219A scalable web crawler framework for Java.
https://github.com/code4craft/webmagic
A scalable web crawler framework for Java. Contribute to code4craft/webmagic development by creating an account on GitHub.
- 220Manage your Java environment
https://github.com/jenv/jenv
Manage your Java environment . Contribute to jenv/jenv development by creating an account on GitHub.
- 221:rocket: Lightning fast and elegant mvc framework for Java8
https://github.com/lets-blade/blade
:rocket: Lightning fast and elegant mvc framework for Java8 - lets-blade/blade
- 222A curated list of awesome JavaFX libraries, books, frameworks, etc...
https://github.com/mhrimaz/AwesomeJavaFX
A curated list of awesome JavaFX libraries, books, frameworks, etc... - mhrimaz/AwesomeJavaFX
- 223java port of Underscore.js
https://github.com/javadev/underscore-java
java port of Underscore.js. Contribute to javadev/underscore-java development by creating an account on GitHub.
- 224A curated list of Microservice Architecture related principles and technologies.
https://github.com/mfornos/awesome-microservices
A curated list of Microservice Architecture related principles and technologies. - mfornos/awesome-microservices
- 225Baeldung
https://www.baeldung.com
In-depth, to-the-point tutorials on Java, Spring, Spring Boot, Security, and REST.
- 226A curated list of awesome loosely performance related JVM stuff. Inspired by awesome-python.
https://github.com/deephacks/awesome-jvm
A curated list of awesome loosely performance related JVM stuff. Inspired by awesome-python. - deephacks/awesome-jvm
- 227Gephi - The Open Graph Viz Platform
https://github.com/gephi/gephi
Gephi - The Open Graph Viz Platform. Contribute to gephi/gephi development by creating an account on GitHub.
- 228🎯 LogCaptor captures log entries for unit and integration testing purposes
https://github.com/Hakky54/log-captor
🎯 LogCaptor captures log entries for unit and integration testing purposes - Hakky54/log-captor
- 229Alibaba Java Diagnostic Tool Arthas/Alibaba Java诊断利器Arthas
https://github.com/alibaba/arthas
Alibaba Java Diagnostic Tool Arthas/Alibaba Java诊断利器Arthas - alibaba/arthas
- 230A curated list of awesome resources for Graal, GraalVM, Truffle and related topics
https://github.com/neomatrix369/awesome-graal
A curated list of awesome resources for Graal, GraalVM, Truffle and related topics - neomatrix369/awesome-graal
- 231A library that generates postman collection and integration tests from java code
https://github.com/cleopatra27/chocotea
A library that generates postman collection and integration tests from java code - cleopatra27/chocotea
- 232Programming & DevOps news, tutorials & tools
https://dzone.com
Programming, Web Development, and DevOps news, tutorials and tools for beginners to experts. Hundreds of free publications, over 1M members, totally free.
- 233Free Java & OpenJDK Info for Daily Java Usage | foojay
https://foojay.io
A place for friends of OpenJDK, foojay provides user-focused Java and OpenJDK technical info and dashboards with free data for everyday Java developers.
- 234Semantic versioning for Java apps.
https://github.com/semver4j/semver4j
Semantic versioning for Java apps. Contribute to semver4j/semver4j development by creating an account on GitHub.
- 235Developer Community
https://community.oracle.com/community/java
What is Oracle Forums? A place where you can connect, learn and explore. Whether you are a product manager, marketing manager, or general tech enthusiast, we welcome you. In Oracle Forums, you can cre...
- 236Most popular Mocking framework for unit tests written in Java
https://github.com/mockito/mockito
Most popular Mocking framework for unit tests written in Java - mockito/mockito
- 237assertions for logging with logback
https://github.com/dm-drogeriemarkt/log-capture
assertions for logging with logback. Contribute to dm-drogeriemarkt/log-capture development by creating an account on GitHub.
- 238Lightweight analysis tool for detecting mutability in Java classes
https://github.com/MutabilityDetector/MutabilityDetector
Lightweight analysis tool for detecting mutability in Java classes - MutabilityDetector/MutabilityDetector
- 239A Java architecture test library, to specify and assert architecture rules in plain Java
https://github.com/TNG/ArchUnit
A Java architecture test library, to specify and assert architecture rules in plain Java - TNG/ArchUnit
- 240A compact and highly efficient workflow and Business Process Management (BPM) platform for developers, system admins and business users.
https://github.com/flowable/flowable-engine
A compact and highly efficient workflow and Business Process Management (BPM) platform for developers, system admins and business users. - flowable/flowable-engine
- 241Testcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.
https://github.com/testcontainers/testcontainers-java
Testcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker containe...
- 242Embulk: Pluggable Bulk Data Loader.
https://github.com/embulk/embulk
Embulk: Pluggable Bulk Data Loader. Contribute to embulk/embulk development by creating an account on GitHub.
- 243Open Source Web Crawler for Java
https://github.com/yasserg/crawler4j
Open Source Web Crawler for Java. Contribute to yasserg/crawler4j development by creating an account on GitHub.
- 244True Object-Oriented Java Web Framework without NULLs, Static Methods, Annotations, and Mutable Objects
https://github.com/yegor256/takes
True Object-Oriented Java Web Framework without NULLs, Static Methods, Annotations, and Mutable Objects - yegor256/takes
- 245XMLUnit for Java 2.x
https://github.com/xmlunit/xmlunit
XMLUnit for Java 2.x. Contribute to xmlunit/xmlunit development by creating an account on GitHub.
- 246Compare JSON in your Unit Tests
https://github.com/lukas-krecan/JsonUnit
Compare JSON in your Unit Tests. Contribute to lukas-krecan/JsonUnit development by creating an account on GitHub.
- 247Improve Service Reliability with AI
https://blog.overops.com
Use AI to enhance software delivery with automated SLO tracking and change impact analysis for better reliability.
- 248A curated list of delightful SAP Commerce resources.
https://github.com/eminyagiz42/awesome-hybris
A curated list of delightful SAP Commerce resources. - eminyagiz42/awesome-sap-commerce
- 249Java rate limiting library based on token-bucket algorithm.
https://github.com/vladimir-bukhtoyarov/bucket4j
Java rate limiting library based on token-bucket algorithm. - bucket4j/bucket4j
- 250JVM version of Pact. Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project.
https://github.com/DiUS/pact-jvm
JVM version of Pact. Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project....
- 251Checklist for code reviews
https://github.com/code-review-checklists/java-concurrency
Checklist for code reviews. Contribute to code-review-checklists/java-concurrency development by creating an account on GitHub.
- 252continuous integration and continuous delivery
https://github.com/ciandcd/awesome-ciandcd
continuous integration and continuous delivery. Contribute to cicdops/awesome-ciandcd development by creating an account on GitHub.
- 253A list of useful Java frameworks, libraries, software and hello worlds examples
https://github.com/Vedenin/useful-java-links
A list of useful Java frameworks, libraries, software and hello worlds examples - Vedenin/useful-java-links
Related Articlesto learn about angular.
- 1Java Programming 101: Beginner's Guide to Object-Oriented Programming
- 2Java Data Types and Variables: A Complete Guide for Beginners
- 3Java Generics: How to Write Type-Safe Code
- 4Java Streams and Lambda Expressions: Comprehensive Guide
- 5Building Web Applications with Java and Spring Boot
- 6Java Web Frameworks Compared: Spring vs. JSF vs. Struts
- 7Building Scalable and Robust Applications with Java EE: Enterprise Java
- 8Java Message Service (JMS) for Enterprise Applications
- 9Android Development: Building Your First App with Java
- 10Using Java for Android App Performance Optimization
FAQ'sto learn more about Angular JS.
mail [email protected] to add more queries here 🔍.
- 1
what can you do with java programming language
- 2
which app is used for java programming
- 3
what is socket programming in java
- 4
what is dynamic programming in java
- 5
what can java programming language be used for
- 6
when was java discontinued
- 7
how to do java programming in laptop
- 8
is java programming language free
- 9
which laptop is best for java programming
- 10
what is java as a programming language
- 11
what can we do with java programming language
- 12
will java be replaced
- 13
is java programming easy to learn
- 14
how popular is java as a programming language
- 15
what can java programming language do
- 16
how can learn java programming
- 17
is java the best programming language
- 18
who made java programming language
- 19
why are generics used in java programming
- 20
which java programming software is the best
- 21
will java ever die
- 22
is java programming hard to learn
- 23
is java programming language
- 24
how long will it take to learn java programming
- 25
how to practice java programming
- 26
how to do java programming in vs code
- 27
is java programming paradigm
- 28
when to use reactive programming java
- 29
how to use netbeans for java programming
- 30
should you learn java or python first
- 31
is java programming language hard to learn
- 32
why reactive programming in java
- 33
was java written in c
- 34
who uses java programming language
- 35
where to start java programming
- 36
where to do java programming
- 37
where to learn java programming
- 38
where to study java programming
- 39
what are the uses of java programming language
- 40
when was java programming language created
- 41
why java programming is simple
- 42
can i do competitive programming in java
- 43
who was java developed by
- 44
which application is used for java programming
- 45
what does java programming do
- 46
does java support procedural programming
- 47
why java programming is used
- 48
what are the features of java programming language
- 49
how to learn java programming for beginners
- 50
why java programming named java
- 51
what is reactive programming java
- 52
how to do java programming in computer
- 53
where to practice java programming
- 54
why functional programming introduced in java 8
- 55
what java programming language
- 56
how to start programming in java
- 57
does java have programming
- 58
where java programming language is used
- 59
can i do java programming on android
- 60
which app is best for java programming
- 61
how to do java programming in notepad
- 62
how can i practice java programming
- 63
what is object oriented programming in java
- 64
how to do java programming in mobile
- 65
which inheritance in java programming is not supported
- 66
what does java programming language look like
- 67
why was java discontinued
- 68
what can you do with java programming
- 69
where we use java programming language
- 70
what are the principles of object oriented programming in java
- 71
what does java programming look like
- 72
how to do java programming
- 73
which of the following is not a java programming tool
- 74
what is the primary focus of java programming
- 75
is java programming hard
- 76
who is the father of java programming language
- 77
which software is used for java programming
- 78
how to learn java programming
- 79
does java support functional programming
- 80
when did java become popular
- 81
where java programming is used
- 82
why was java programming language created
- 83
should you learn java or javascript first
- 84
where we can do java programming
- 85
should java be updated
- 86
is java programming difficult
- 87
can i do java programming on ipad
- 88
which software is needed for java programming
- 89
did javascript come from java
- 90
was java discontinued
- 91
why java is object oriented programming
- 92
who owns java programming language
- 93
why java is popular programming language
- 94
who invented java programming
- 95
does java have programming language
- 96
what are java programming language
- 97
how to download java programming language
- 98
what are the basics of java programming
- 99
how long does it take to learn java programming
- 100
can you do functional programming in java
- 101
who created java programming
- 102
what are the advantages of java programming language
- 103
what is the basic structure of java programming
- 104
what are the features of object-oriented programming in java
- 105
when java was created
- 106
which is a reserved word in the java programming language
- 107
will java become obsolete
- 108
will programming jobs disappear
- 109
is java programming easy
- 110
why java is the best programming language
- 111
does java support asynchronous programming
- 112
what is generic programming in java
- 113
should you learn java or c++ first
- 114
how does java programming work
- 115
what is functional programming in java
- 116
did java or javascript come first
- 117
what job can you get with java programming
- 118
is java programming still relevant
- 119
why java is called an object oriented programming language
- 120
what can java programming be used for
- 121
do java programming online
- 122
which programming paradigm does java follow
- 123
why java programming language is named as java
- 124
how to use eclipse for java programming
More Sitesto check out once you're finished browsing here.
https://www.0x3d.site/
0x3d is designed for aggregating information.
https://nodejs.0x3d.site/
NodeJS Online Directory
https://cross-platform.0x3d.site/
Cross Platform Online Directory
https://open-source.0x3d.site/
Open Source Online Directory
https://analytics.0x3d.site/
Analytics Online Directory
https://javascript.0x3d.site/
JavaScript Online Directory
https://golang.0x3d.site/
GoLang Online Directory
https://python.0x3d.site/
Python Online Directory
https://swift.0x3d.site/
Swift Online Directory
https://rust.0x3d.site/
Rust Online Directory
https://scala.0x3d.site/
Scala Online Directory
https://ruby.0x3d.site/
Ruby Online Directory
https://clojure.0x3d.site/
Clojure Online Directory
https://elixir.0x3d.site/
Elixir Online Directory
https://elm.0x3d.site/
Elm Online Directory
https://lua.0x3d.site/
Lua Online Directory
https://c-programming.0x3d.site/
C Programming Online Directory
https://cpp-programming.0x3d.site/
C++ Programming Online Directory
https://r-programming.0x3d.site/
R Programming Online Directory
https://perl.0x3d.site/
Perl Online Directory
https://java.0x3d.site/
Java Online Directory
https://kotlin.0x3d.site/
Kotlin Online Directory
https://php.0x3d.site/
PHP Online Directory
https://react.0x3d.site/
React JS Online Directory
https://angular.0x3d.site/
Angular JS Online Directory