Mercurial > hg > graal-jvmci-8
annotate src/share/vm/runtime/perfMemory.cpp @ 8854:754c24457b20
7112912: Message "Error occurred during initialization of VM" on boxes with lots of RAM
Summary: Ergonomics now also takes available virtual memory into account when deciding for a heap size. The helper method to determine the maximum allocatable memory block now uses the appropriate OS specific calls to retrieve available virtual memory for the java process. In 32 bit environments this method now also searches for the maximum actually reservable amount of memory. Merge previously separate implementations for Linux/BSD/Solaris into a single method.
Reviewed-by: jmasa, tamao
author | tschatzl |
---|---|
date | Wed, 27 Mar 2013 19:21:18 +0100 |
parents | b9a9ed0f8eeb |
children | e89b54bf4e51 |
rev | line source |
---|---|
0 | 1 /* |
6842
b9a9ed0f8eeb
7197424: update copyright year to match last edit in jdk8 hotspot repository
mikael
parents:
6197
diff
changeset
|
2 * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
470
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
470
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
470
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "memory/allocation.inline.hpp" | |
27 #include "runtime/arguments.hpp" | |
28 #include "runtime/java.hpp" | |
29 #include "runtime/mutex.hpp" | |
30 #include "runtime/mutexLocker.hpp" | |
31 #include "runtime/os.hpp" | |
32 #include "runtime/perfData.hpp" | |
33 #include "runtime/perfMemory.hpp" | |
34 #include "runtime/statSampler.hpp" | |
35 #include "utilities/globalDefinitions.hpp" | |
0 | 36 |
434 | 37 // Prefix of performance data file. |
38 const char PERFDATA_NAME[] = "hsperfdata"; | |
39 | |
40 // Add 1 for the '_' character between PERFDATA_NAME and pid. The '\0' terminating | |
41 // character will be included in the sizeof(PERFDATA_NAME) operation. | |
42 static const size_t PERFDATA_FILENAME_LEN = sizeof(PERFDATA_NAME) + | |
43 UINT_CHARS + 1; | |
44 | |
0 | 45 char* PerfMemory::_start = NULL; |
46 char* PerfMemory::_end = NULL; | |
47 char* PerfMemory::_top = NULL; | |
48 size_t PerfMemory::_capacity = 0; | |
49 jint PerfMemory::_initialized = false; | |
50 PerfDataPrologue* PerfMemory::_prologue = NULL; | |
51 | |
52 void perfMemory_init() { | |
53 | |
54 if (!UsePerfData) return; | |
55 | |
56 PerfMemory::initialize(); | |
57 } | |
58 | |
59 void perfMemory_exit() { | |
60 | |
61 if (!UsePerfData) return; | |
62 if (!PerfMemory::is_initialized()) return; | |
63 | |
64 // if the StatSampler is active, then we don't want to remove | |
65 // resources it may be dependent on. Typically, the StatSampler | |
66 // is disengaged from the watcher thread when this method is called, | |
67 // but it is not disengaged if this method is invoked during a | |
68 // VM abort. | |
69 // | |
70 if (!StatSampler::is_active()) | |
71 PerfDataManager::destroy(); | |
72 | |
73 // remove the persistent external resources, if any. this method | |
74 // does not unmap or invalidate any virtual memory allocated during | |
75 // initialization. | |
76 // | |
77 PerfMemory::destroy(); | |
78 } | |
79 | |
80 void PerfMemory::initialize() { | |
81 | |
82 if (_prologue != NULL) | |
83 // initialization already performed | |
84 return; | |
85 | |
86 size_t capacity = align_size_up(PerfDataMemorySize, | |
87 os::vm_allocation_granularity()); | |
88 | |
89 if (PerfTraceMemOps) { | |
90 tty->print("PerfDataMemorySize = " SIZE_FORMAT "," | |
91 " os::vm_allocation_granularity = " SIZE_FORMAT "," | |
92 " adjusted size = " SIZE_FORMAT "\n", | |
93 PerfDataMemorySize, | |
94 os::vm_allocation_granularity(), | |
95 capacity); | |
96 } | |
97 | |
98 // allocate PerfData memory region | |
99 create_memory_region(capacity); | |
100 | |
101 if (_start == NULL) { | |
102 | |
103 // the PerfMemory region could not be created as desired. Rather | |
104 // than terminating the JVM, we revert to creating the instrumentation | |
105 // on the C heap. When running in this mode, external monitoring | |
106 // clients cannot attach to and monitor this JVM. | |
107 // | |
108 // the warning is issued only in debug mode in order to avoid | |
109 // additional output to the stdout or stderr output streams. | |
110 // | |
111 if (PrintMiscellaneous && Verbose) { | |
112 warning("Could not create PerfData Memory region, reverting to malloc"); | |
113 } | |
114 | |
6197 | 115 _prologue = NEW_C_HEAP_OBJ(PerfDataPrologue, mtInternal); |
0 | 116 } |
117 else { | |
118 | |
119 // the PerfMemory region was created as expected. | |
120 | |
121 if (PerfTraceMemOps) { | |
122 tty->print("PerfMemory created: address = " INTPTR_FORMAT "," | |
123 " size = " SIZE_FORMAT "\n", | |
124 (void*)_start, | |
125 _capacity); | |
126 } | |
127 | |
128 _prologue = (PerfDataPrologue *)_start; | |
129 _end = _start + _capacity; | |
130 _top = _start + sizeof(PerfDataPrologue); | |
131 } | |
132 | |
133 assert(_prologue != NULL, "prologue pointer must be initialized"); | |
134 | |
135 #ifdef VM_LITTLE_ENDIAN | |
136 _prologue->magic = (jint)0xc0c0feca; | |
137 _prologue->byte_order = PERFDATA_LITTLE_ENDIAN; | |
138 #else | |
139 _prologue->magic = (jint)0xcafec0c0; | |
140 _prologue->byte_order = PERFDATA_BIG_ENDIAN; | |
141 #endif | |
142 | |
143 _prologue->major_version = PERFDATA_MAJOR_VERSION; | |
144 _prologue->minor_version = PERFDATA_MINOR_VERSION; | |
145 _prologue->accessible = 0; | |
146 | |
147 _prologue->entry_offset = sizeof(PerfDataPrologue); | |
148 _prologue->num_entries = 0; | |
149 _prologue->used = 0; | |
150 _prologue->overflow = 0; | |
151 _prologue->mod_time_stamp = 0; | |
152 | |
153 OrderAccess::release_store(&_initialized, 1); | |
154 } | |
155 | |
156 void PerfMemory::destroy() { | |
157 | |
158 assert(_prologue != NULL, "prologue pointer must be initialized"); | |
159 | |
160 if (_start != NULL && _prologue->overflow != 0) { | |
161 | |
162 // This state indicates that the contiguous memory region exists and | |
163 // that it wasn't large enough to hold all the counters. In this case, | |
164 // we output a warning message to the user on exit if the -XX:+Verbose | |
165 // flag is set (a debug only flag). External monitoring tools can detect | |
166 // this condition by monitoring the _prologue->overflow word. | |
167 // | |
168 // There are two tunables that can help resolve this issue: | |
169 // - increase the size of the PerfMemory with -XX:PerfDataMemorySize=<n> | |
170 // - decrease the maximum string constant length with | |
171 // -XX:PerfMaxStringConstLength=<n> | |
172 // | |
173 if (PrintMiscellaneous && Verbose) { | |
174 warning("PerfMemory Overflow Occurred.\n" | |
175 "\tCapacity = " SIZE_FORMAT " bytes" | |
176 " Used = " SIZE_FORMAT " bytes" | |
177 " Overflow = " INT32_FORMAT " bytes" | |
178 "\n\tUse -XX:PerfDataMemorySize=<size> to specify larger size.", | |
179 PerfMemory::capacity(), | |
180 PerfMemory::used(), | |
181 _prologue->overflow); | |
182 } | |
183 } | |
184 | |
185 if (_start != NULL) { | |
186 | |
187 // this state indicates that the contiguous memory region was successfully | |
188 // and that persistent resources may need to be cleaned up. This is | |
189 // expected to be the typical condition. | |
190 // | |
191 delete_memory_region(); | |
192 } | |
193 | |
194 _start = NULL; | |
195 _end = NULL; | |
196 _top = NULL; | |
197 _prologue = NULL; | |
198 _capacity = 0; | |
199 } | |
200 | |
201 // allocate an aligned block of memory from the PerfData memory | |
202 // region. This method assumes that the PerfData memory region | |
203 // was aligned on a double word boundary when created. | |
204 // | |
205 char* PerfMemory::alloc(size_t size) { | |
206 | |
207 if (!UsePerfData) return NULL; | |
208 | |
209 MutexLocker ml(PerfDataMemAlloc_lock); | |
210 | |
211 assert(_prologue != NULL, "called before initialization"); | |
212 | |
213 // check that there is enough memory for this request | |
214 if ((_top + size) >= _end) { | |
215 | |
216 _prologue->overflow += (jint)size; | |
217 | |
218 return NULL; | |
219 } | |
220 | |
221 char* result = _top; | |
222 | |
223 _top += size; | |
224 | |
225 assert(contains(result), "PerfData memory pointer out of range"); | |
226 | |
227 _prologue->used = (jint)used(); | |
228 _prologue->num_entries = _prologue->num_entries + 1; | |
229 | |
230 return result; | |
231 } | |
232 | |
233 void PerfMemory::mark_updated() { | |
234 if (!UsePerfData) return; | |
235 | |
236 _prologue->mod_time_stamp = os::elapsed_counter(); | |
237 } | |
238 | |
239 // Returns the complete path including the file name of performance data file. | |
240 // Caller is expected to release the allocated memory. | |
241 char* PerfMemory::get_perfdata_file_path() { | |
242 char* dest_file = NULL; | |
243 | |
244 if (PerfDataSaveFile != NULL) { | |
245 // dest_file_name stores the validated file name if file_name | |
246 // contains %p which will be replaced by pid. | |
6197 | 247 dest_file = NEW_C_HEAP_ARRAY(char, JVM_MAXPATHLEN, mtInternal); |
0 | 248 if(!Arguments::copy_expand_pid(PerfDataSaveFile, strlen(PerfDataSaveFile), |
249 dest_file, JVM_MAXPATHLEN)) { | |
6197 | 250 FREE_C_HEAP_ARRAY(char, dest_file, mtInternal); |
0 | 251 if (PrintMiscellaneous && Verbose) { |
252 warning("Invalid performance data file path name specified, "\ | |
253 "fall back to a default name"); | |
254 } | |
255 } else { | |
256 return dest_file; | |
257 } | |
258 } | |
259 // create the name of the file for retaining the instrumentation memory. | |
6197 | 260 dest_file = NEW_C_HEAP_ARRAY(char, PERFDATA_FILENAME_LEN, mtInternal); |
0 | 261 jio_snprintf(dest_file, PERFDATA_FILENAME_LEN, |
262 "%s_%d", PERFDATA_NAME, os::current_process_id()); | |
263 | |
264 return dest_file; | |
265 } |