- A Concurrent Affair - https://www.concurrentaffair.org -

More Information about the Sync Points

I created the strategy and thread monitor that supply and use the additional debugging information I mentioned before — a class index and a method index. Now I know exactly in which method a synchronization point originates.

The CompactSynchronizedBlockDebugStrategy creates a method database in a text file with the following format:

00003192 00000001: OneSyncBlockTest.main([Ljava/lang/String;)V
00003193 00000000: FewSyncBlockTest.<init>()V
00003193 00000001: FewSyncBlockTest.main([Ljava/lang/String;)V

Each line begins with two 8-digit hexadecimal numbers, the class and the method index. The human-readable name consisting of the class name, the method name, and the descriptor follow after the colon. Whenever synchronization points are encountered in the bytecode, these indices are stored in the buffer as well.

When the thread monitor is run in a mode that uses this debug information, it can load the method database and decypher the indices. The annotated log then looks like this:

// Note: Attempting to process sync points - main exited
// Total number of compact sync points so far: 2803
2 0 00003157 00000018 java.lang.StringBuffer.append(C)Ljava/lang/StringBuffer;
1 0 00003157 00000018 java.lang.StringBuffer.append(C)Ljava/lang/StringBuffer;
...
1 0 00003157 00000004 java.lang.StringBuffer.length()I
2 0 00003157 00000004 java.lang.StringBuffer.length()I
...
1 0 00003157 00000035 java.lang.StringBuffer.toString()Ljava/lang/String;
2 0 00003157 00000035 java.lang.StringBuffer.toString()Ljava/lang/String;
1 0 000030dd 00000002 java.io.ExpiringCache.get(Ljava/lang/String;)Ljava/lang/String;
2 0 000030dd 00000002 java.io.ExpiringCache.get(Ljava/lang/String;)Ljava/lang/String;
1 0 00003090 00000001 java.security.Permissions.add(Ljava/security/Permission;)V
...
1 0 00003087 00000001 java.io.FilePermissionCollection.add(Ljava/security/Permission;)V
2 0 00003087 00000001 java.io.FilePermissionCollection.add(Ljava/security/Permission;)V
...
1 0 00003084 00000001 java.security.BasicPermissionCollection.add(Ljava/security/Permission;)V
2 0 00003084 00000001 java.security.BasicPermissionCollection.add(Ljava/security/Permission;)V
2 0 00003090 00000001 java.security.Permissions.add(Ljava/security/Permission;)V
1 0 000030c0 00000015 java.net.URL.hashCode()I
2 0 000030c0 00000015 java.net.URL.hashCode()I
2 0 000030c9 00000005 java.security.SecureClassLoader.getProtectionDomain(Ljava/security/CodeSource;)
    Ljava/security/ProtectionDomain;
1 0 0000316c 0000000b java.util.Hashtable.get(Ljava/lang/Object;)Ljava/lang/Object;
2 0 0000316c 0000000b java.util.Hashtable.get(Ljava/lang/Object;)Ljava/lang/Object;
1 0 0000316c 0000000d java.util.Hashtable.put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
2 0 0000316c 0000000d java.util.Hashtable.put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
...
1 0 000030b6 00000002 sun.misc.Launcher$AppClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;
2 0 000030b6 00000002 sun.misc.Launcher$AppClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;
2 0 000030b6 00000002 sun.misc.Launcher$AppClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;
1 0 000030b6 00000002 sun.misc.Launcher$AppClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;
2 0 000030b6 00000002 sun.misc.Launcher$AppClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;
1 0 00003193 00000001 FewSyncBlockTest.main([Ljava/lang/String;)V
2 0 00003193 00000001 FewSyncBlockTest.main([Ljava/lang/String;)V
1 0 00003193 00000001 FewSyncBlockTest.main([Ljava/lang/String;)V
1 0 00003193 00000001 FewSyncBlockTest.main([Ljava/lang/String;)V
2 0 00003193 00000001 FewSyncBlockTest.main([Ljava/lang/String;)V
2 0 00003193 00000001 FewSyncBlockTest.main([Ljava/lang/String;)V
1 0 00003193 00000001 FewSyncBlockTest.main([Ljava/lang/String;)V
2 0 00003193 00000001 FewSyncBlockTest.main([Ljava/lang/String;)V
// Note: getting updated thread list from VM
//    13: put ($$$threadID$$$ = 6, name = Signal Dispatcher)
//     3: put ($$$threadID$$$ = 2, name = Finalizer)
//     4: put ($$$threadID$$$ = 1, name = Reference Handler)
//     1: put ($$$threadID$$$ = 0, name = main)
// Note: Finished processing sync points - main exited
// -- The application exited --
// Total number of compact sync points: 2803

The above is actually an abridged trace of what happens after the main method is entered. The comment says “main exited” because that’s when the buffer got pushed.

A lot of the synchronization points happen in java.lang.StringBuffer, mostly in void append(char). A few synchronization points also happen in classes dealing with permissions and a class loader. The bottom eight synchronization points are points that actually happen in the program’s main method.

I’m gonna mull this over now for a little bit and go to sleep. I don’t exactly know what it means, but it’s definitely interesting.

[1] [2]Share [3]