@@ -56,27 +56,28 @@ public void test() throws Throwable {
56
56
String [] events = new String []{JfrEvent .ObjectAllocationOutsideTLAB .getName ()};
57
57
Recording recording = startRecording (events );
58
58
59
+ /* Do a GC before the allocations to avoid that the GC interferes with the test. */
60
+ System .gc ();
61
+
59
62
/*
60
63
* Use a separate thread for allocating the objects, to have better control over the TLAB
61
64
* and to make sure the objects are actually allocated outside the TLAB.
62
65
*/
63
66
Thread testThread = new Thread (() -> {
64
- final long largeObjectThreshold = SerialAndEpsilonGCOptions .LargeArrayThreshold .getValue ();
65
- final int arraySize = NumUtil .safeToInt (largeObjectThreshold - 1024 );
67
+ int arrayDataSize = arrayDataSizeForOutOfTLABAllocation ();
66
68
67
- // Allocate a small object to make sure we have a TLAB.
68
- Object o = new Object ();
69
- GraalDirectives .blackhole (o );
69
+ /* Allocate a small object to make sure we have a TLAB. */
70
+ GraalDirectives .blackhole (new Object ());
70
71
71
- allocateByteArray (arraySize / Byte .BYTES );
72
- allocateCharArray (arraySize / Character .BYTES );
72
+ /* Allocate large arrays that don't fit into the TLAB. */
73
+ GraalDirectives .blackhole (allocateByteArray (arrayDataSize / Byte .BYTES ));
74
+ GraalDirectives .blackhole (allocateCharArray (arrayDataSize / Character .BYTES ));
73
75
}, TEST_THREAD_NAME );
74
76
75
77
testThread .start ();
76
78
testThread .join ();
77
79
78
80
stopRecording (recording , TestObjectAllocationOutsideTLABEvent ::validateEvents );
79
-
80
81
}
81
82
82
83
@ NeverInline ("Prevent escape analysis." )
@@ -89,9 +90,17 @@ private static char[] allocateCharArray(int length) {
89
90
return new char [length ];
90
91
}
91
92
93
+ /**
94
+ * Returns the required array data size in bytes such that an array is too large to be allocated
95
+ * in the TLAB, yet still small enough to fit within an aligned heap chunk.
96
+ */
97
+ private static int arrayDataSizeForOutOfTLABAllocation () {
98
+ long largeObjectThreshold = SerialAndEpsilonGCOptions .LargeArrayThreshold .getValue ();
99
+ return NumUtil .safeToInt (largeObjectThreshold - 512 );
100
+ }
101
+
92
102
private static void validateEvents (List <RecordedEvent > events ) {
93
- final long largeObjectThreshold = SerialAndEpsilonGCOptions .LargeArrayThreshold .getValue ();
94
- final int arrayLength = NumUtil .safeToInt (largeObjectThreshold - 1024 );
103
+ int arrayDataSize = arrayDataSizeForOutOfTLABAllocation ();
95
104
96
105
boolean foundByteArray = false ;
97
106
boolean foundCharArray = false ;
@@ -105,7 +114,7 @@ private static void validateEvents(List<RecordedEvent> events) {
105
114
long allocationSize = event .<Long > getValue ("allocationSize" );
106
115
String className = event .<RecordedClass > getValue ("objectClass" ).getName ();
107
116
108
- if (allocationSize >= arrayLength ) {
117
+ if (allocationSize >= arrayDataSize ) {
109
118
if (className .equals (char [].class .getName ())) {
110
119
foundCharArray = true ;
111
120
} else if (className .equals (byte [].class .getName ())) {
@@ -119,5 +128,4 @@ private static void validateEvents(List<RecordedEvent> events) {
119
128
assertTrue (foundByteArray );
120
129
assertTrue (foundCharArray );
121
130
}
122
-
123
131
}
0 commit comments