3 liens privés
Some of the Java Flight Recording events (JDK 17)
jdk.NativeMethodSample jdk.ActiveRecording jdk.ActiveSetting jdk.JVMInformation jdk.OSInformation jdk.InitialSystemProperty jdk.InitialEnvironmentVariable jdk.CPUInformation jdk.CPUTimeStampCounter jdk.ClassLoaderStatistics jdk.ThreadAllocationStatistics jdk.PhysicalMemory jdk.ThreadDump jdk.NativeLibrary jdk.CompilerConfiguration jdk.CodeCacheStatistics jdk.CodeCacheConfiguration jdk.CodeSweeperStatistics jdk.CodeSweeperConfiguration jdk.IntFlag jdk.UnsignedIntFlag jdk.LongFlag jdk.UnsignedLongFlag jdk.DoubleFlag jdk.BooleanFlag jdk.StringFlag jdk.GCConfiguration jdk.GCSurvivorConfiguration jdk.GCTLABConfiguration jdk.GCHeapConfiguration jdk.YoungGenerationConfiguration jdk.ThreadEnd jdk.ThreadCPULoad jdk.ThreadStart jdk.CPULoad jdk.JavaThreadStatistics jdk.ClassLoadingStatistics jdk.CompilerStatistics jdk.ExceptionStatistics jdk.GCHeapSummary jdk.G1HeapSummary jdk.MetaspaceSummary jdk.MetaspaceChunkFreeListSummary jdk.GCPhasePauseLevel1 jdk.GCPhasePauseLevel2 jdk.GCReferenceStatistics jdk.G1EvacuationYoungStatistics jdk.G1EvacuationOldStatistics jdk.TenuringDistribution jdk.G1MMU jdk.G1BasicIHOP jdk.G1AdaptiveIHOP jdk.EvacuationInformation jdk.GCPhasePause jdk.GarbageCollection jdk.YoungGarbageCollection jdk.G1GarbageCollection jdk.ExecuteVMOperation jdk.ThreadContextSwitchRate jdk.NetworkUtilization
Java memory improvment since Java 8
List of JVM options per JVM versions
Negative Lookeahd :
SetFlag: ((?!Hpa).)*$
- Search for string which do not contains "Hpa" after SetFlag
- Do not forget "$" if multi-line regexp is activated
Testing string :
Match : SetFlag: TestKO
No Match : SetFlag: HpaTestOK
From Java 8 to 21 : improvment
via les castcodeurs
Reminder classloader, classname :
Exit0.class.getSimpleName() = Exit0
Exit0.class.getCanonicalName() = com.gorki.Exit0
<instance>.getClass().getSimpleName() =
<instance>.getClass().getCanonicalName() = null
<instance>.getClass().getName() = com.gorki.Exit0$1
<instance>.getClass().getTypeName() = com.gorki.Exit0$1
<instance>.getClass().getPackage().getName() = com.gorki
<instance>.getClass().isAnonymousClass() = true
With :
package com.gorki;
import java.util.ArrayList;
import java.util.Random;
public class Exit0 {
public static void main(String... args) {
Runnable t = new Runnable() {
@Override
public void run() {
}
};
System.out.println("Exit0.class.getSimpleName() = " + Exit0.class.getSimpleName());
System.out.println("Exit0.class.getCanonicalName() = " + Exit0.class.getCanonicalName());
System.out.println("<instance>.getClass().getSimpleName() = " + t.getClass().getSimpleName());
System.out.println("<instance>.getClass().getCanonicalName() = " + t.getClass().getCanonicalName());
System.out.println("<instance>.getClass().getName() = " + t.getClass().getName());
System.out.println("<instance>.getClass().getTypeName() = " + t.getClass().getTypeName());
System.out.println("<instance>.getClass().getPackage().getName() = " + t.getClass().getPackage().getName());
System.out.println("<instance>.getClass().isAnonymousClass() = " + t.getClass().isAnonymousClass());
}
}
Generate a self certificate without adding altName with the IP can lead to an error
The reason this error in java 1.8.0_181 is because this update includes security improvements for LDAP support
-Dcom.sun.jndi.ldap.object.disableEndpointIdentification=true
Java class to test SSL
Additional parameter :
-Djavax.net.debug=ssl,handshake
-Djavax.net.debug=ssl,manager
-Djavax.net.debug=all
Pour avoir la description d'une méthode version bytecode :
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.util.concurrent.ThreadPoolExecutor;
public class ByteCodeDescriptor {
public static void main(String... args) {
Class clazz = ThreadPoolExecutor.class;
String result= ByteCodeDescriptor.getDescriptorForClass(clazz);
System.out.println("class = " + result);
for (Method m : ThreadPoolExecutor.class.getMethods()) {
String resultM= ByteCodeDescriptor.getDescriptor(m);
System.out.println("method = " + m);
System.out.println("method result = " + m.getName() + resultM);
}
for (Constructor c : ThreadPoolExecutor.class.getConstructors()) {
String resultM= ByteCodeDescriptor.getDescriptor(c);
System.out.println("constructor = " + c);
System.out.println("constructor result = " + resultM);
}
}
static String getDescriptorForClass(final Class c)
{
if(c.isPrimitive())
{
if(c==byte.class)
return "B";
if(c==char.class)
return "C";
if(c==double.class)
return "D";
if(c==float.class)
return "F";
if(c==int.class)
return "I";
if(c==long.class)
return "J";
if(c==short.class)
return "S";
if(c==boolean.class)
return "Z";
if(c==void.class)
return "V";
throw new RuntimeException("Unrecognized primitive "+c);
}
if(c.isArray()) return c.getName().replace('.', '/');
return ('L'+c.getName()+';').replace('.', '/');
}
static String getDescriptor(Executable e) {
String s = "(";
for (final Class c : e.getParameterTypes())
s += getDescriptorForClass(c);
s += ')';
if (e instanceof Method) {
Method m = (Method) e;
return m.getName() + s + getDescriptorForClass(m.getReturnType());
} else if (e instanceof Constructor) {
Constructor c = (Constructor) e;
return "<init>" + s + getDescriptorForClass(void.class);
}
throw new RuntimeException("Unrecognized primitive "+e);
}
}
Dumping des informations mémoires.
Une JVM configuré pour 7Go en prend 13G en mémoire.
Ajout du flag :
-XX:NativeMemoryTracking=summary
Attention impact un peu les performances.
Résultat, la différence était dans "Symbol" : Here is the NMT report about the symbol allocations, such as the string table and constant pool.
Et en effet cette JVM manipule beaucoup de chaines qu'elle garde en mémoire qui pourrait être interned
https://stackoverflow.com/questions/10578984/what-is-java-string-interning
http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#intern()
Basically doing String.intern() on a series of strings will ensure that all strings having same contents share same memory. So if you have list of names where 'john' appears 1000 times, by interning you ensure only one 'john' is actually allocated memory.
Heap dump pour la suite.
Dans un remote debugger :
this.getClass().getResource('/' + String.class.getName().replace('.', '/') + ".class")
-XX:NativeMemoryTracking=summary
which produces an overview of the memory usage by the components of the JVM. It actually gives a pretty good picture of the "cost" of having a JVM.
Enabling detailed native memory tracking (NMT) causes a 5% to 10% performance overhead. The summary mode merely has an impact in memory usage as shown below and is usually enough.
It is necessary to note that while the above command indicate a scale in KB for the JVM it really means KiB.
JVM native memory tracking report
$ jcmd $(pidof java) VM.native_memory
Example of output :
Native Memory Tracking:
Total: reserved=7168324KB, committed=5380868KB
- Java Heap (reserved=4456448KB, committed=4456448KB)
(mmap: reserved=4456448KB, committed=4456448KB)
- Class (reserved=1195628KB, committed=165788KB)
(classes #28431)
( instance classes #26792, array classes #1639)
(malloc=5740KB #87822)
(mmap: reserved=1189888KB, committed=160048KB)
( Metadata: )
( reserved=141312KB, committed=139876KB)
( used=135945KB)
( free=3931KB)
( waste=0KB =0.00%)
( Class space:)
( reserved=1048576KB, committed=20172KB)
( used=17864KB)
....
Java memory dump on outofmemory
-XX:+PrintGCDateStamps
-verbose:gc
-XX:+PrintGCDetails
-Xloggc:"<path to log>"
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=<path to dump>`date`.hprof
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintGCDetails
-XX:+PrintSafepointStatistics
-XX:PrintSafepointStatisticsCount=1
-XX:+SafepointTimeout
-XX:SafepointTimeoutDelay=<ms before timeout log is printed>
Speak of GC
LocalDateTime ne gère PAS les timezone :)
See : OffsetDateTime
Consulter les MBeans d'une JVM en mode ligne de commande sans serveur X
jvms
open <id>
beans
GUI for multiple decompiler
five different decompilers (DJ-GUI/Core, Procyon, CFR, Fernflower and Krakatau).
Liste de décompilateur Java :
JDCore (very fast)
CFR (very good and well-supported decompiler for Java 8)
Jadx, fast and with Android support
Procyon
Fernflower
JAD (very fast, but outdated)
La galère enfin résolue mais c'est pas simple : jvisualvm over ssh
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=<jmx-remote-port>
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.local.only=false
-Djava.rmi.server.hostname=localhost
Attention au "-Djava.rmi.server.hostname=localhost", c'est ça qui fait que ça marche.
ps -ef | grep <java-processname>
netstat -lp | grep <process-id>
On récupère le deuxième port dynamique (le premier c'est le JMX)
Puis ouverture des tunnels (en cascade si on veut) :
ssh login@machine1 -L 15666:localhost:15666 -L 33429:localhost:33429
ssh login@machine2 -L 15666:localhost:15666 -L 33429:localhost:33429
Sur la jconsole ou visualvm :
service:jmx:rmi:///jndi/rmi://localhost:15666/jmxrmi
Et bing, ça marche....
Et si on n'a pas de tunneling SSH, il y a une option qui consiste à avoir un serveur HTTP qui sait exécuter du CGI : https://docs.oracle.com/javase/7/docs/platform/rmi/spec/rmi-arch6.html
On le configure pour exécuter le script cgi-bin/java-rmi.cgi. Par contre je pense que ça ne marche que pour faire des appels RMI distants et pas pour la JVisualVM... encore que, peut-être...
Pense-bête :
from Java 5.0, it is better to use the -agentlib:jdwp
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000
Before Java 5.0, use -Xdebug and -Xrunjdwp
-Xdebug -Xrunjdwp:server=y,transport=dt_socket,suspend=n,address=8000