Reference-object (opens in a new tab) classes
var referenceQueue = new ReferenceQueue<Person>();
var referent = new Person("John", "Doe");
var reference = new WeakReference<>(referent, referenceQueue);
-
To mark the
Reference
whosereferent
to be garbage collected, there are 3 ways:-
reference.enqueue()
The
referent
will be garbage collected and enqueued immediately. -
referent = null
The
referent
will be garbage collected and enqueued, but not as immediate asreference.enqueue()
. -
reference.clear()
Only clears the
referent
field, without enqueuing thereference
.
-
-
java.lang.ref.ReferenceQueue
- A
ReferenceQueue
is used to trackReference
objects whosereferent
has been garbage collected, by usingReferenceQueue::poll
. When areferent
is garbage collected, itsReference
will be enqued to theReferenceQueue
it was created with. - To be placed on a
ReferenceQueue
, aReference
object must be created with aReferenceQueue
via itsConstructor
. Soft
andweak
reference objects can be created with areference queue
or not, butphantom reference
objects must be created with areference queue
.- You can use
ReferenceQueue::poll
to check if anyreferences
have been garbage collected.
- A
-
Reference
types-
java.lang.ref.SoftReference
- Keep objects alive provided there’s enough memory.
- Suitable for implementing a cache for external resources, so the cache will be effective until JVM runs out of memory.
-
java.lang.ref.WeakReference
- Keep objects alive only while they’re strongly reachable. When they become weakly reachable only, they are eligible for collection.
- Suitable for implementing a cache for transient data, so the cache be cleared more eagerly.
- If GC finds that an object is weakly reachable (reachable only through weak references), it'll clear the weak references to that object immediately.
-
java.lang.ref.PhantomReference
Phantom reference
objects are placed in theirreference queue
after they become phantomly reachable, but before their reference field is cleared. This is so a program can perform post-finalization cleanup and clear thephantom reference
upon completion of the cleanup.- Lets you clean up after finalization but before the space is reclaimed (replaces or augments the use of
finalize()
) - it can be used instead of a
finalize
method, guaranteeing that the object is not resurrected during finalization. This allows the object to be garbage collected in a single cycle, rather than needing to wait for a second GC cycle to ensure that it has not been resurrected. - A second use is to detect exactly when an object has been removed from memory (by using in combination with a
ReferenceQueue
object), ensuring that its memory is available, for example deferring allocation of a large amount of memory (e.g., a large image) until previous memory is freed. - In
Java 8 and earlier versions
, the reference needs to be cleared before the memory for a finalized referent can be reclaimed. A change inJava 9
will allow memory from a finalized referent to be reclaimable immediately.
-
-
Resources
Garbage Collectors
G1
-
Pros
- Better overall performance than previous collectors
- Can do most work concurrently without stopping application threads
- It uses non-continuous spaces, by dividing heap into equally sized regions. The eden, survivor, and old generations are logical sets of these regions and are not contiguous. This enables the G1 to efficiently deal with very large heaps.
- String deduplication via flag
-XX:+UseStringDeduplication
-
Cons
- Designed for heaps
> 4GB
, doesn't perform well with small heaps. If theG1
has too little heap available, you will see “Full GC
”s in theGC log
. Pause time
target configurable via flag-XX:MaxGCPauseMillis
but not a real-time collector.
- Designed for heaps
-
Resources
ZGC
-
Performance characteristics
O(1)
pause time regardless ofheap size
Average GC pause time
around0.05ms (50 microseconds)
Max GC pause time
around0.5ms (500 microseconds)
Generational ZGC
solves theallocation stall
issue (whenthe rate of new object allocation
is faster thanthe rate at which ZGC can reclaim memory
.), see Introducing Generational ZGC (opens in a new tab)
-
Resources
Shenandoah GC
Java Memory Model
Metrics
-
Get arguments of a running JVM process
-
JDK - jps (opens in a new tab)
jps -lvm
-
-
GC.class_stats
command requires-XX:+UnlockDiagnosticVMOptions
-
java -X
shows non-standard options
Examine loaded classes
-
Use JVM option
-verbose:class
[0.688s][info][class,load] ch.qos.logback.classic.Logger source: file:/mnt/c/Users/Takechiyo/.m2/repository/ch/qos/logback/logback-classic/1.2.10/logback-classic-1.2.10.jar
-
Use Java
API
-
Determine the file containing the class
var clazz = Logger.class; var resourceName = clazz.getSimpleName() + ".class"; System.out.println(clazz.getCanonicalName() + ": " + clazz.getResource(resourceName)); // ch.qos.logback.classic.Logger: jar:file:/C:/Users/Takechiyo/.m2/repository/ch/qos/logback/logback-classic/1.2.10/logback-classic-1.2.10.jar!/ch/qos/logback/classic/Logger.class
-
Determine the classloader and file containing the class
private static void examineClass(Class<?> classObject) { var fullName = classObject.getName(); var resourceName = fullName.replaceAll("\\.", "/") + ".class"; try { var clazz = Class.forName(fullName); var loader = clazz.getClassLoader(); System.out.println("Class: " + clazz.getName()); System.out.println("Loader: " + loader); var url = ClassLoader.getSystemResource(resourceName); System.out.println("Loaded from: " + url); System.out.println("All locations: "); var e = ClassLoader.getSystemResources(resourceName); while (e.hasMoreElements()) { url = e.nextElement(); System.out.println(" " + url); } } catch (Exception e) { e.printStackTrace(); } } examineClass(ch.qos.logback.classic.Logger.class); /** Class: ch.qos.logback.classic.Logger Loader: jdk.internal.loader.ClassLoaders$AppClassLoader@77556fd Loaded from: jar:file:/C:/Users/Takechiyo/.m2/repository/ch/qos/logback/logback-classic/1.2.10/logback-classic-1.2.10.jar!/ch/qos/logback/classic/Logger.class All locations: jar:file:/C:/Users/Takechiyo/.m2/repository/ch/qos/logback/logback-classic/1.2.10/logback-classic-1.2.10.jar!/ch/qos/logback/classic/Logger.class */
-
Classloaders
Fundamental classloaders
- Primordial/Bootstrap classloader
- Loads the most fundamental Java library classes
- Part of JVM
- Extension/Platform classloader
- Typical name:
sun.misc.Launcher$ExtClassLoader
- Security extension
- Typical name:
- Application/System classloader
- Typical name:
sun.misc.Launcher$AppClassLoader
/jdk.internal.loader.ClassLoaders$AppClassLoader
- Most widely used
- Loads classes and JAR files on the classpath
- Typical name:
The parent-delegation model
- Because class loading is always delegated first to the parent of the class loading hierarchy, the most trusted repository (the core API) is checked first, followed by the standard extensions, then the local files that are on the class path. Finally, classes that are located in any repository that your own class loader can access, are accessible. This system prevents code from less-trusted sources from replacing trusted core API classes by assuming the same name as part of the core API.
Notes
- You can load classes from a directory or JAR file that is not already on the classpath, by creating your own
URLClassLoader
instance. This is commonly done to load plugins. - The second parameter in the call
Class.forName(className, true, loader)
ensures that the static initialization of the class happens after loading. You definitely want that to happen. - Do NOT use the
ClassLoader.loadClass
method. It does not run the static initializers. - The
URLClassLoader
loads classes from the file system. If you want to load a class from somewhere else, you need to write your own class loader by extendingjava.lang.ClassLoader
and implementingprotected Class<?> findClass(String name) throws ClassNotFoundException
. - When loading classes dynamically from external sources like plugins, we should use the corresponding Classloader to load target classes to ensure the target URL of the class
Code snippets
Get Classpath Resources
ClassLoader.getSystemResources("")?.collect { URL classPath ->
def list = []
new File(classPath.toURI()).traverse(type: FileType.FILES) {
list << it.path
}
list
}
private static List<String> getClassPathResources(String fileExtension) {
try {
List<Path> classPaths = EnumerationUtils.toList(ClassLoader.getSystemResources("")).stream().map(u -> {
try {
return Paths.get(u.toURI());
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}).collect(Collectors.toList());
return classPaths.stream().flatMap(p -> {
try {
return Files.walk(p).filter(d -> Files.isRegularFile(d))
.filter(f -> Strings.isNullOrEmpty(fileExtension) || f.toString().endsWith(String.format(".%s", fileExtension)))
.map(i -> i.toAbsolutePath().toString());
} catch (IOException e) {
throw new RuntimeException(e);
}
}).collect(Collectors.toList());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Bytecode
Determine the version of Java class file
javap -v $class_file | grep version
Bytecode versions matrix
Java SE | Released | Major | Supported majors |
---|---|---|---|
1.0.2 | May 1996 | 45 | 45 |
1.1 | February 1997 | 45 | 45 |
1.2 | December 1998 | 46 | 45 .. 46 |
1.3 | May 2000 | 47 | 45 .. 47 |
1.4 | February 2002 | 48 | 45 .. 48 |
5.0 | September 2004 | 49 | 45 .. 49 |
6 | December 2006 | 50 | 45 .. 50 |
7 | July 2011 | 51 | 45 .. 51 |
8 | March 2014 | 52 | 45 .. 52 |
9 | September 2017 | 53 | 45 .. 53 |
10 | March 2018 | 54 | 45 .. 54 |
11 | September 2018 | 55 | 45 .. 55 |
12 | March 2019 | 56 | 45 .. 56 |
13 | September 2019 | 57 | 45 .. 57 |
14 | March 2020 | 58 | 45 .. 58 |
15 | September 2020 | 59 | 45 .. 59 |
16 | March 2021 | 60 | 45 .. 60 |
17 | September 2021 | 61 | 45 .. 61 |
18 | March 2022 | 62 | 45 .. 62 |
19 | September 2022 | 63 | 45 .. 63 |
CLI
jar
List files included in a JAR file
-
jar tf $jar_file
- The listed file path is the identifier you used to reference the file, and it can be used to extract or update the particular file.
e.g.
jar tf playground-spring-boot-cli-0.1-SNAPSHOT.jar | grep properties 90:BOOT-INF/classes/application.properties 95:META-INF/maven/cq-playground/playground-spring-boot-cli/pom.properties
Extract files from a JAR file
-
jar xvf $jar_file
Extract all files
-
jar xvf $jar_file [$file1, $file2...]
Extract specified files, note the file name must contain path from within the archive, file name alone is not enough.
e.g.
jar xf playground-spring-boot-cli-0.1-SNAPSHOT.jar BOOT-INF/classes/application.properties
Note:
unzip
can also extract files from a JAR file.
Update a file from a JAR file
jar uf $jar_file [$file1, $file2...]
javac
Show all lint keys
javac --help-lint
The supported keys for -Xlint are:
all Enable all warnings
auxiliaryclass Warn about an auxiliary class that is hidden in a source file, and is used from other files.
cast Warn about use of unnecessary casts.
classfile Warn about issues related to classfile contents.
deprecation Warn about use of deprecated items.
dep-ann Warn about items marked as deprecated in JavaDoc but not using the @Deprecated annotation.
divzero Warn about division by constant integer 0.
empty Warn about empty statement after if.
exports Warn about issues regarding module exports.
fallthrough Warn about falling through from one case of a switch statement to the next.
finally Warn about finally clauses that do not terminate normally.
lossy-conversions Warn about possible lossy conversions in compound assignment.
missing-explicit-ctor Warn about missing explicit constructors in public and protected classes in exported packages.
module Warn about module system related issues.
opens Warn about issues regarding module opens.
options Warn about issues relating to use of command line options.
output-file-clash Warn when an output file is overwritten during compilation. This can occur, for example,
on case-insensitive filesystems. Covers class files, native header files, and source files.
overloads Warn about issues regarding method overloads.
overrides Warn about issues regarding method overrides.
path Warn about invalid path elements on the command line.
processing Warn about issues regarding annotation processing.
rawtypes Warn about use of raw types.
removal Warn about use of API that has been marked for removal.
requires-automatic Warn about use of automatic modules in the requires clauses.
requires-transitive-automatic Warn about automatic modules in requires transitive.
serial Warn about Serializable classes that do not have a serialVersionUID field.
Also warn about other suspect declarations in Serializable and Externalizable classes and interfaces.
static Warn about accessing a static member using an instance.
strictfp Warn about unnecessary use of the strictfp modifier.
synchronization Warn about synchronization attempts on instances of value-based classes.
text-blocks Warn about inconsistent white space characters in text block indentation.
this-escape Warn when a constructor invokes a method that could be overriden in an external subclass.
Such a method would execute before the subclass constructor completes its initialization.
try Warn about issues relating to use of try blocks (i.e. try-with-resources).
unchecked Warn about unchecked operations.
varargs Warn about potentially unsafe vararg methods.
preview Warn about use of preview language features.
none Disable all warnings
Can be turned on with javac -Xlint:$key
java
-
Resources
java - cheatsheet
java - Specify system properties
java -D$property_name=$property_value $class_name
Use jcmd $JVM_PID VM.system_properties
to verify
java - Display system property settings
java -XshowSettings:properties
java - Use @
prefix to reference files containing arguments
-
Use the
@
prefix to identify an argument file that containsjava
options and class names.e.g.
java @path1/options @path2/classes
java - Debug SSL/TLS Connections
-
Use system property
javax.net.debug=ssl
, for options check reference below.# The current options are: all: Turn on all debugging ssl: Turn on SSL debugging # The following can be used with the ssl option to select what type of debug information to print: defaultctx: Print default SSL initialization handshake: Print each handshake message keygen: Print key generation data keymanager: Print key manager tracing pluggability: Print pluggability tracing record: Enable per-record tracing respmgr: Print status response manager tracing session: Print session activity sessioncache: Print session cache tracing sslctx: Print SSLContext tracing trustmanager: Print trust manager tracing # Messages generated from the handshake option can be widened with these options: data: Hex dump of each handshake message verbose: Verbose handshake message printing # Messages generated from the record option can be widened with these options: plaintext: Hex dump of record plaintext packet: Print raw SSL/TLS packets
-
Resources
java - View security properties, security providers, and TLS-related settings
java -XshowSettings:security
java - List security debugging options
java -Djava.security.debug=help
Apply additional JVM options via JDK_JAVA_OPTIONS
and JAVA_TOOL_OPTIONS
JDK_JAVA_OPTIONS
- Only works for
Java 9+
and thejava
CLI
JAVA_TOOL_OPTIONS
- In addition to
java
, also works for other Java tools such asjar
andjavac
# Set environment variable
export JDK_JAVA_OPTIONS="-Dspring.profiles.active=dev"
# Run JVM process
mvn spring-boot:run
# A message will display as confirmation
NOTE: Picked up JDK_JAVA_OPTIONS: -Dspring.profiles.active=dev
Caveat: JAVA_OPTS
is not standard and not guaranteed to work.
-
Resource
- Oracle Help Center - Java SE 17 - Tools Reference - The java command - Using the JDK_JAVA_OPTIONS Launcher Environment Variable (opens in a new tab)
- Oracle - Java SE 21 - Troubleshooting Guide - Appendices - C Environment Variables and System Properties - JAVA_TOOL_OPTIONS (opens in a new tab)
- Stack Overflow - What is the difference between JDK_JAVA_OPTIONS and JAVA_TOOL_OPTIONS when using Java 11? (opens in a new tab)
JVM Options
JVM Options - GC
-
-XX:+DisableExplicitGC
, causes the VM to ignore calls toSystem.gc()
. -
Logging
-
JDK 8 and earlier
- Print GC log
-Xloggc:/opt/logs/gc-%t.log
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintGCCause
-XX:+PrintTenuringDistribution
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=10
-XX:GCLogFileSize=5M
- Print GC log
-
JDK 9+
-
Resources
-
JVM Options - Logging
JVM Options - Memory Settings
-
Heap
-
-Xms
is equivalent to-XX:InitialHeapSize
. -
-Xmx
is equivalent to-XX:MaxHeapSize
. -
-Xmx
should be between 80% and 100% of the machine's physical memory. If you set-Xmx
too small, the application server may fail with anOutOfMemory
error. If you set-Xmx
too large, the memory's footprint is larger and you run the risk of Java's heap being swapped out, causing other performance problems. -
-Xms
should be approximately half of the-Xmx
setting. If you have historical data about your application server's stable memory-usage point, then set-Xms
to be around that value.
-
-
Metaspace (formely PermGen)
-
-XX:MaxMetaspaceSize
is the maximum amount of native memory that can be allocated for class metadata. The default value depends on the platform. -
-XX:MetaspaceSize
is the initial amount of native memory that can be allocated for class metadata. The default size of is platform-dependent and rangesfrom 12 MB to about 20 MB
. -
-XX:MaxMetaspaceFreeRatio
is the maximum percentage of class metadata free space to class metadata used space after a garbage collection. The default value is70
. -
-XX:MinMetaspaceFreeRatio
is the minimum percentage of class metadata free space to class metadata used space after a garbage collection. The default value is40
. -
If you observe classes being unloaded during full garbage collections, you should use
-XX:PermSize
and-XX:MaxPermSize
command line options to size the permanent generation space. To avoid full garbage collections that may expand or shrink the committed size of the permanent generation space, set-XX:PermSize
and-XX:MaxPermSize
to the same value. -
Resources
-
JVM Options - Compiler (JIT)
-XX:+PrintCompilation
prints a message to the console when a method is compiled.-XX:+PrintCompilation2
prints a message to the console when a method is compiled, and includes the time it took to compile the method.
JVM Options - Performance - based on JMC Automated Analysis Results
-
Java Application
-
Memory
-
Free Physical Memory
Having little free memory
may lead toswapping
, which is very expensive. To avoid this, eitherdecrease the memory usage
orincrease the amount of available memory
.
-
-
Exceptions
-
Thrown Errors
Investigate the thrown errors to see if they can be avoided. Errors indicate that something went wrong with the code execution and should never be used for flow control.
-
-
-
JVM Internals
-
Stackdepth Setting
Some stack traces were truncated in this recording. If more detailed traces are required, increase the
-XX:FlightRecorderOptions=stackdepth=<value>
value. -
GC Configuration
-
Compressed Oops
Not using
Compressed Ordinary Object Pointers
when theheap size
isbelow 32 GB
wastes memory and will lead to unnecessary cache pressure. Use the JVM argument-XX:+UseCompressedOops
to enable this feature.Refer to OpenJDK Wiki - CompressedOops (opens in a new tab) for details.
-
-
-
Environment
-
Processes
-
Competing Processes
If this is a server environment, it may be good to only run other critical processes on that machine.
-
-
JVM Options - Resources
jps
jps - List all local JVM processes
jps -lvm
jcmd
-
Comes with JDK 7 and onwards
-
Resources
jcmd - List all local JVM processes
jcmd / jcmd -l
# e.g.
$ jcmd
3157 org.gradle.launcher.GradleMain bootRun
2710 org.gradle.launcher.daemon.bootstrap.GradleDaemon 8.5
5145 jdk.jcmd/sun.tools.jcmd.JCmd
3390 cq.playground.spring.poc.kafka.nonreactive.MainApp
jcmd - List all diagnostic commands for a specific process
jcmd $PID [help]
If PID
is 0
, the command is sent to all JVM processes
# e.g.
$ jcmd 3390
3390:
The following commands are available:
Compiler.CodeHeap_Analytics
Compiler.codecache
Compiler.codelist
Compiler.directives_add
Compiler.directives_clear
Compiler.directives_print
Compiler.directives_remove
Compiler.perfmap
Compiler.queue
GC.class_histogram
GC.finalizer_info
GC.heap_dump
GC.heap_info
GC.run
GC.run_finalization
JFR.check
JFR.configure
JFR.dump
JFR.start
JFR.stop
JFR.view
JVMTI.agent_load
JVMTI.data_dump
ManagementAgent.start
ManagementAgent.start_local
ManagementAgent.status
ManagementAgent.stop
System.native_heap_info
System.trim_native_heap
Thread.dump_to_file
Thread.print
VM.cds
VM.class_hierarchy
VM.classes
VM.classloader_stats
VM.classloaders
VM.command_line
VM.dynlibs
VM.events
VM.flags
VM.info
VM.log
VM.metaspace
VM.native_memory
VM.set_flag
VM.stringtable
VM.symboltable
VM.system_properties
VM.systemdictionary
VM.uptime
VM.version
help
jcmd - Help for a specific diagnostic command
jcmd <PID/Main Class> help $command
eg: jcmd 38388 help VM.version
jcmd - List system properties of a JVM process
jcmd $PID VM.system_properties | sort
# e.g.
$ jcmd 3390 VM.system_properties
3390:
#Sun Feb 04 15:06:55 AEDT 2024
CONSOLE_LOG_CHARSET=UTF-8
FILE_LOG_CHARSET=UTF-8
LOG_FILE=/tmp/spring.log
LOG_PATH=/tmp
PID=3390
catalina.base=/tmp/tomcat.8080.470854316564232780
catalina.home=/tmp/tomcat.8080.470854316564232780
catalina.useNaming=false
file.encoding=UTF-8
file.separator=/
java.awt.headless=true
jcmd - List JVM flags
jcmd $PID VM.flags | tr " " "\n" | sort
or
jinfo -flags $PID | tr " " "\n" | sort
jinfo
jinfo - List system properties of a JVM process
jinfo -sysprops $PID | sort
jinfo - Print the value of the specified VM flag
jinfo -flag $name
jinfo - Enable/Disable the specified VM flag
jinfo -flag [+|-]$name
JFR (Java Flight Recorder)
-
Parameters
-
settings
=pathSpecifies the path and name of the event settings file (of type JFC).
By default, 2 settings available, stored in
$JAVA_HOME/lib/jfr
Default
: Less than1%
overheadProfile
: Around2%
overhead
-
Refer to
-XX:StartFlightRecording
under Advanced Runtime Options for Java (opens in a new tab) for details
-
-
jcmd
commandsJFR.check JFR.configure JFR.dump JFR.start JFR.stop
-
Custom Event
Must invoke
Event.commit()
to record values. -
Streaming
-
Native Memeory
-
Resources
- YouTube - Oracle Learning - Java Mission Control and Flight Recorder Demo Series (opens in a new tab)
- Oracle Help Center - Java SE 17 - Troubleshooting Guide - Troubleshoot Performance Issues Using Flight Recorder (opens in a new tab)
- Oracle Help Center - Java SE 17 - Flight Recorder API Programmer’s Guide (opens in a new tab)
- InfoQ - Continuous Monitoring with JDK Flight Recorder (JFR) (opens in a new tab)
- BellSoft - JDK Flight Recorder, The Programmatic Way (opens in a new tab)
JMX
JDP
-
A manageable JVM is one that has the JMX agent running.
-
Resources
GUI Tools
JMC (JDK Mission Control)
jol (Java Object Layout)
-
Estimate how much memory an object takes
-
Resources
VisualVM
-
Cannot start up, failing to find Java runtime
-
Use
visualvm.conf
-
Edit
$VISUALVM_INSTALLATION/etc/visualvm.conf
-
Uncomment
visualvm_jdkhome="/path/to/jdk"
-
Specify JDK directory
-
Resources
-
-
Use command line arguments
visualvm.exe --jdkhome $JAVA_HOME
-
References
-
Bytecode
-
JVM
- Wikipedia - Java virtual machine - Virtual machine architecture (opens in a new tab)
- Oracle - Java Language and Virtual Machine Specifications (opens in a new tab)
- Ionut Balosin - HotSpot JVM Performance Tuning Guidelines (opens in a new tab)
- DZone - 7 JVM Arguments of Highly Effective Applications (opens in a new tab)
- jvmperf: Java Performance Workshop (opens in a new tab)