Wed, 20 Aug 2014 14:34:40 +0200
8055525: Bigapp weblogic+medrec fails to startup after JDK-8038423
Summary: If large pages are enabled and configured in Linux, the VM always pre-commits the entire space. The VM fails verification of the commit of the initial heap because some internal data structure marked all memory pages of the heap as committed during initialization. This makes the code think that we attempted a double-commit during first allocation of the heap. Remove the initial marking of memory pages of the heap to committed.
Reviewed-by: mgerdin
1 /*
2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
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 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
25 #include "precompiled.hpp"
26 #include "gc_implementation/g1/g1PageBasedVirtualSpace.hpp"
27 #include "oops/markOop.hpp"
28 #include "oops/oop.inline.hpp"
29 #include "services/memTracker.hpp"
30 #ifdef TARGET_OS_FAMILY_linux
31 # include "os_linux.inline.hpp"
32 #endif
33 #ifdef TARGET_OS_FAMILY_solaris
34 # include "os_solaris.inline.hpp"
35 #endif
36 #ifdef TARGET_OS_FAMILY_windows
37 # include "os_windows.inline.hpp"
38 #endif
39 #ifdef TARGET_OS_FAMILY_aix
40 # include "os_aix.inline.hpp"
41 #endif
42 #ifdef TARGET_OS_FAMILY_bsd
43 # include "os_bsd.inline.hpp"
44 #endif
45 #include "utilities/bitMap.inline.hpp"
47 G1PageBasedVirtualSpace::G1PageBasedVirtualSpace() : _low_boundary(NULL),
48 _high_boundary(NULL), _committed(), _page_size(0), _special(false), _executable(false) {
49 }
51 bool G1PageBasedVirtualSpace::initialize_with_granularity(ReservedSpace rs, size_t page_size) {
52 if (!rs.is_reserved()) {
53 return false; // Allocation failed.
54 }
55 assert(_low_boundary == NULL, "VirtualSpace already initialized");
56 assert(page_size > 0, "Granularity must be non-zero.");
58 _low_boundary = rs.base();
59 _high_boundary = _low_boundary + rs.size();
61 _special = rs.special();
62 _executable = rs.executable();
64 _page_size = page_size;
66 assert(_committed.size() == 0, "virtual space initialized more than once");
67 uintx size_in_bits = rs.size() / page_size;
68 _committed.resize(size_in_bits, /* in_resource_area */ false);
70 return true;
71 }
74 G1PageBasedVirtualSpace::~G1PageBasedVirtualSpace() {
75 release();
76 }
78 void G1PageBasedVirtualSpace::release() {
79 // This does not release memory it never reserved.
80 // Caller must release via rs.release();
81 _low_boundary = NULL;
82 _high_boundary = NULL;
83 _special = false;
84 _executable = false;
85 _page_size = 0;
86 _committed.resize(0, false);
87 }
89 size_t G1PageBasedVirtualSpace::committed_size() const {
90 return _committed.count_one_bits() * _page_size;
91 }
93 size_t G1PageBasedVirtualSpace::reserved_size() const {
94 return pointer_delta(_high_boundary, _low_boundary, sizeof(char));
95 }
97 size_t G1PageBasedVirtualSpace::uncommitted_size() const {
98 return reserved_size() - committed_size();
99 }
101 uintptr_t G1PageBasedVirtualSpace::addr_to_page_index(char* addr) const {
102 return (addr - _low_boundary) / _page_size;
103 }
105 bool G1PageBasedVirtualSpace::is_area_committed(uintptr_t start, size_t size_in_pages) const {
106 uintptr_t end = start + size_in_pages;
107 return _committed.get_next_zero_offset(start, end) >= end;
108 }
110 bool G1PageBasedVirtualSpace::is_area_uncommitted(uintptr_t start, size_t size_in_pages) const {
111 uintptr_t end = start + size_in_pages;
112 return _committed.get_next_one_offset(start, end) >= end;
113 }
115 char* G1PageBasedVirtualSpace::page_start(uintptr_t index) {
116 return _low_boundary + index * _page_size;
117 }
119 size_t G1PageBasedVirtualSpace::byte_size_for_pages(size_t num) {
120 return num * _page_size;
121 }
123 MemRegion G1PageBasedVirtualSpace::commit(uintptr_t start, size_t size_in_pages) {
124 // We need to make sure to commit all pages covered by the given area.
125 guarantee(is_area_uncommitted(start, size_in_pages), "Specified area is not uncommitted");
127 if (!_special) {
128 os::commit_memory_or_exit(page_start(start), byte_size_for_pages(size_in_pages), _executable,
129 err_msg("Failed to commit pages from "SIZE_FORMAT" of length "SIZE_FORMAT, start, size_in_pages));
130 }
131 _committed.set_range(start, start + size_in_pages);
133 MemRegion result((HeapWord*)page_start(start), byte_size_for_pages(size_in_pages) / HeapWordSize);
134 return result;
135 }
137 MemRegion G1PageBasedVirtualSpace::uncommit(uintptr_t start, size_t size_in_pages) {
138 guarantee(is_area_committed(start, size_in_pages), "checking");
140 if (!_special) {
141 os::uncommit_memory(page_start(start), byte_size_for_pages(size_in_pages));
142 }
144 _committed.clear_range(start, start + size_in_pages);
146 MemRegion result((HeapWord*)page_start(start), byte_size_for_pages(size_in_pages) / HeapWordSize);
147 return result;
148 }
150 bool G1PageBasedVirtualSpace::contains(const void* p) const {
151 return _low_boundary <= (const char*) p && (const char*) p < _high_boundary;
152 }
154 #ifndef PRODUCT
155 void G1PageBasedVirtualSpace::print_on(outputStream* out) {
156 out->print ("Virtual space:");
157 if (special()) out->print(" (pinned in memory)");
158 out->cr();
159 out->print_cr(" - committed: " SIZE_FORMAT, committed_size());
160 out->print_cr(" - reserved: " SIZE_FORMAT, reserved_size());
161 out->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", p2i(_low_boundary), p2i(_high_boundary));
162 }
164 void G1PageBasedVirtualSpace::print() {
165 print_on(tty);
166 }
167 #endif