JDK Flight Recorder introduced in OpenJDK 11.
This feature is low overhead of profiling and be able to used on production environment.
We would like to use JDK Flight Recorder instead of Java logging Framework.
In contrast to the logging framework, we will introduce the points in using the JDK Flight Recorder.
3. 0 1 400 4 154 000 1 800
JFR disabled JFR enabled,
stackdepth=1
log4j OFF log4j INFO j.u.logging OFF j.u.logging INFO Redirected
System.out
NANOS/OPERATION
JMC, 8 THREADS
Logging Benchmark
120 000 00043 000 000
JFR
Jfokus Developer Conference 2018 Mission Possible -Near Zero overhead profiling
java.util.logging System.outJDK Flight Recorder Apache Log4j
ON
OFF
ON
OFF
ON
OFF
16. JFR
@Category({"Java Development Kit", "Security"})
@Label("TLS Handshake")
@Name("jdk.TLSHandshake")
@Description("Parameters used in TLS Handshake")
public final class TLSHandshakeEvent extends AbstractJDKEvent {
@Label("Peer Host")
public String peerHost;
@Label("Peer Port")
public int peerPort;
@Label("Protocol Version")
public String protocolVersion;
@Label("Cipher Suite")
public String cipherSuite;
@Label("Certificate Id")
@Description("Peer Certificate Id")
@CertificateId
public long certificateId;
}
/src/jdk.jfr/share/classes/jdk/jfr/events/TLSHandshakeEvent.java
24. JFR
Java API
Events
JavaVM
/ OS Events
Repository
(disk storage)
Global
Buffer
-a
-b
Global
Buffer
Global
Buffer
Global
Buffer
Global
Buffer
Global
Buffer
Global
Buffer
Global
Buffer
When full, is copied into
Thread
Buffer
Event
Event
Event
Event
When full,
is copied into
JFR File
When triggered, is dumped into
36. 0 1 400 4 154 000 1 800
JFR disabled JFR enabled,
stackdepth=1
log4j OFF log4j INFO j.u.logging OFF j.u.logging INFO Redirected
System.out
NANOS/OPERATION
JMC, 8 THREADS
Logging Benchmark
120 000 00043 000 000
Jfokus Developer Conference 2018 Mission Possible -Near Zero overhead profiling
java.util.logging System.outJDK Flight Recorder Apache Log4j
ON
OFF
ON
OFF
ON
OFF
JFR
37. public static void setProperty(String key, String datum) {
check("setProperty." + key);
props.put(key, datum);
invalidateSMCache(key); /* See below. */
SecurityPropertyModificationEvent spe = new SecurityPropertyModificationEvent();
// following is a no-op if event is disabled
spe.key = key;
spe.value = datum;
spe.commit();
if (EventHelper.isLoggingSecurity()) {
EventHelper.logSecurityPropertyEvent(key, datum);
}
}
/src/java.base/share/classes/java/security/Security.java
@Enabled(false) Event
!?
!?
39. “ ” Event
@Enabled(true)
@StackTrace(true)
@Registered(true)
public abstract class Event extends jdk.internal.event.Event {
protected Event() {
}
final public void begin() {
}
final public void end() {
}
final public void commit() {
}
final public boolean shouldCommit() {
return false;
}
....
/src/jdk.jfr/share/classes/jdk/jfr/Event.java
40. public static void setProperty(String key, String datum) {
check("setProperty." + key);
props.put(key, datum);
invalidateSMCache(key); /* See below. */
SecurityPropertyModificationEvent spe = new SecurityPropertyModificationEvent();
// following is a no-op if event is disabled
spe.key = key;
spe.value = datum;
spe.commit();
if (EventHelper.isLoggingSecurity()) {
EventHelper.logSecurityPropertyEvent(key, datum);
}
}
@Enabled(false) Event
JIT Compiler
Dead Code Elimination
spe.commit();
/src/java.base/share/classes/java/security/Security.java
41. Public class Example {
static Event event;
public static void main(String[] args) {
event = new Event();
event.key = key;
event.value = datum;
event.commit();
}
JIT Compiler EA (Escape Analysis)
Public class Example {
public static void main(String[] args) {
Event event = new Event();
record(event);
}
public static record(Event event) {
event.key = key;
event.value = datum;
event.commit();
}
GlobalEscape
ArgEscape
Public class Example {
public static void main(String[] args) {
Event event = new Event();
event.key = key;
event.value = datum;
event.commit();
}
NoEscape
JIT Compiler
Scalar Replacement
42. public static void setProperty(String key, String datum) {
check("setProperty." + key);
props.put(key, datum);
invalidateSMCache(key); /* See below. */
SecurityPropertyModificationEvent spe = new SecurityPropertyModificationEvent();
// following is a no-op if event is disabled
spe.key = key;
spe.value = datum;
spe.commit();
if (EventHelper.isLoggingSecurity()) {
EventHelper.logSecurityPropertyEvent(key, datum);
}
}
/src/java.base/share/classes/java/security/Security.java
@Enabled(false) Event
- Escape Analysis -
GlobalEscape ArgEscape NoEscape
43. public static void setProperty(String key, String datum) {
check("setProperty." + key);
props.put(key, datum);
invalidateSMCache(key); /* See below. */
SecurityPropertyModificationEvent spe = new SecurityPropertyModificationEvent();
// following is a no-op if event is disabled
spe.key = key;
spe.value = datum;
spe.commit();
if (EventHelper.isLoggingSecurity()) {
EventHelper.logSecurityPropertyEvent(key, datum);
}
}
@Enabled(false) Event
Scalar Replacement
spe.key = key; ! String scalar_1 = key;
spe.value = datum; ! String scalar_2 = value;
/src/java.base/share/classes/java/security/Security.java
44. public static void setProperty(String key, String datum) {
check("setProperty." + key);
props.put(key, datum);
invalidateSMCache(key); /* See below. */
SecurityPropertyModificationEvent spe = new SecurityPropertyModificationEvent();
// following is a no-op if event is disabled
spe.key = key;
spe.value = datum;
spe.commit();
if (EventHelper.isLoggingSecurity()) {
EventHelper.logSecurityPropertyEvent(key, datum);
}
}
@Enabled(false) Event
spe.key = key; ! String scalar_1 = key;
spe.value = datum; ! String scalar_2 = value;
JIT Compiler
Dead Code Elimination
/src/java.base/share/classes/java/security/Security.java
45. public static void setProperty(String key, String datum) {
check("setProperty." + key);
props.put(key, datum);
invalidateSMCache(key); /* See below. */
SecurityPropertyModificationEvent spe = new SecurityPropertyModificationEvent();
// following is a no-op if event is disabled
spe.key = key;
spe.value = datum;
spe.commit();
if (EventHelper.isLoggingSecurity()) {
EventHelper.logSecurityPropertyEvent(key, datum);
}
}
/src/java.base/share/classes/java/security/Security.java
@Enabled(false) Event
spe.key = key; ! String scalar_1 = key;
spe.value = datum; ! String scalar_2 = value;
‼
!!
46. 0 1 400 4 154 000 1 800
JFR disabled JFR enabled,
stackdepth=1
log4j OFF log4j INFO j.u.logging OFF j.u.logging INFO Redirected
System.out
NANOS/OPERATION
JMC, 8 THREADS
Logging Benchmark
120 000 00043 000 000
Jfokus Developer Conference 2018 Mission Possible -Near Zero overhead profiling
java.util.logging System.outJDK Flight Recorder Apache Log4j
ON
OFF
ON
OFF
ON
OFF
JFR
47. @Enabled(true)
@StackTrace(true)
@Registered(true)
public abstract class Event extends jdk.internal.event.Event {
protected Event() {
}
final public void begin() {
}
final public void end() {
}
final public void commit() {
}
final public boolean shouldCommit() {
return false;
}
....
@Enabled(true) Event
Event “ ”
ASM : Bytecode Manipulation Library
final public void begin() {
startTime = EventHandler.timestamp();
}
final public void end() {
duration = EventHandler.duration(startTime);
}
final public void commit() {
if (!isEnable()) {
return;
}
if (startTime == 0) {
....
}
final public boolean shouldCommit() {
....
48. public static void setProperty(String key, String datum) {
check("setProperty." + key);
props.put(key, datum);
invalidateSMCache(key); /* See below. */
SecurityPropertyModificationEvent spe = new SecurityPropertyModificationEvent();
// following is a no-op if event is disabled
spe.key = key;
spe.value = datum;
spe.commit();
if (EventHelper.isLoggingSecurity()) {
EventHelper.logSecurityPropertyEvent(key, datum);
}
}
/src/java.base/share/classes/java/security/Security.java
@Enabled(true) Event