1 /*
2 * Copyright (c) 2016, 2017, 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 */
24
25 #ifndef SHARE_VM_CLASSFILE_PACKAGEENTRY_HPP
26 #define SHARE_VM_CLASSFILE_PACKAGEENTRY_HPP
27
28 #include "classfile/moduleEntry.hpp"
29 #include "oops/symbol.hpp"
30 #include "utilities/growableArray.hpp"
31 #include "utilities/hashtable.hpp"
32 #include "utilities/macros.hpp"
33 #include "utilities/ostream.hpp"
34 #if INCLUDE_JFR
35 #include "jfr/support/jfrTraceIdExtension.hpp"
36 #endif
37
38
39 // A PackageEntry basically represents a Java package. It contains:
40 // - Symbol* containing the package's name.
41 // - ModuleEntry* for this package's containing module.
42 // - a field indicating if the package is exported unqualifiedly or to all
43 // unnamed modules.
44 // - a growable array containing other module entries that this
45 // package is exported to.
46 //
47 // Packages can be exported in the following 3 ways:
48 // - not exported: the package does not have qualified or unqualified exports.
49 // - qualified exports: the package has been explicitly qualified to at least
50 // one particular module or has been qualifiedly exported
51 // to all unnamed modules.
52 // Note: being exported to all unnamed is a form of a qualified
53 // export. It is equivalent to the package being explicitly
54 // exported to all current and future unnamed modules.
55 // - unqualified exports: the package is exported to all modules.
56 //
57 // A package can transition from:
58 // - being not exported, to being exported either in a qualified or unqualified manner
59 // - being qualifiedly exported, to unqualifiedly exported. Its exported scope is widened.
60 //
61 // A package cannot transition from:
62 // - being unqualifiedly exported, to exported qualifiedly to a specific module.
63 // This transition attempt is silently ignored in set_exported.
64 // - being qualifiedly exported to not exported.
65 // Because transitions are only allowed from less exposure to greater exposure,
66 // the transition from qualifiedly exported to not exported would be considered
67 // a backward direction. Therefore the implementation considers a package as
68 // qualifiedly exported even if its export-list exists but is empty.
69 //
70 // The Mutex Module_lock is shared between ModuleEntry and PackageEntry, to lock either
71 // data structure.
72
73 // PKG_EXP_UNQUALIFIED and PKG_EXP_ALLUNNAMED indicate whether the package is
74 // exported unqualifiedly or exported to all unnamed modules. They are used to
75 // set the value of _export_flags. Field _export_flags and the _qualified_exports
76 // list are used to determine a package's export state.
77 // Valid states are:
78 //
79 // 1. Package is not exported
80 // _export_flags is zero and _qualified_exports is null
81 // 2. Package is unqualifiedly exported
82 // _export_flags is set to PKG_EXP_UNQUALIFIED
83 // _qualified_exports may or may not be null depending on whether the package
84 // transitioned from qualifiedly exported to unqualifiedly exported.
85 // 3. Package is qualifiedly exported
86 // _export_flags may be set to PKG_EXP_ALLUNNAMED if the package is also
87 // exported to all unnamed modules
88 // _qualified_exports will be non-null
89 // 4. Package is exported to all unnamed modules
90 // _export_flags is set to PKG_EXP_ALLUNNAMED
91 // _qualified_exports may or may not be null depending on whether the package
92 // is also qualifiedly exported to one or more named modules.
93 #define PKG_EXP_UNQUALIFIED 0x0001
94 #define PKG_EXP_ALLUNNAMED 0x0002
95 #define PKG_EXP_UNQUALIFIED_OR_ALL_UNAMED (PKG_EXP_UNQUALIFIED | PKG_EXP_ALLUNNAMED)
96
97 class PackageEntry : public HashtableEntry<Symbol*, mtModule> {
98 private:
99 ModuleEntry* _module;
100 // Indicates if package is exported unqualifiedly or to all unnamed. Access to
101 // this field is protected by the Module_lock.
102 int _export_flags;
103 // Used to indicate for packages with classes loaded by the boot loader that
104 // a class in that package has been loaded. And, for packages with classes
105 // loaded by the boot loader from -Xbootclasspath/a in an unnamed module, it
106 // indicates from which class path entry.
107 s2 _classpath_index;
108 bool _must_walk_exports;
109 // Contains list of modules this package is qualifiedly exported to. Access
110 // to this list is protected by the Module_lock.
111 GrowableArray<ModuleEntry*>* _qualified_exports;
112 JFR_ONLY(DEFINE_TRACE_ID_FIELD;)
113
114 // Initial size of a package entry's list of qualified exports.
115 enum {QUAL_EXP_SIZE = 43};
116
117 public:
118 void init() {
119 _module = NULL;
120 _export_flags = 0;
121 _classpath_index = -1;
122 _must_walk_exports = false;
123 _qualified_exports = NULL;
124 }
125
126 // package name
127 Symbol* name() const { return literal(); }
128
129 // the module containing the package definition
130 ModuleEntry* module() const { return _module; }
131 void set_module(ModuleEntry* m) { _module = m; }
132
133 // package's export state
134 bool is_exported() const { // qualifiedly or unqualifiedly exported
135 assert_locked_or_safepoint(Module_lock);
136 return module()->is_open() ||
137 ((_export_flags & PKG_EXP_UNQUALIFIED_OR_ALL_UNAMED) != 0) ||
138 has_qual_exports_list();
139 }
140 // Returns true if the package has any explicit qualified exports or is exported to all unnamed
141 bool is_qual_exported() const {
142 assert_locked_or_safepoint(Module_lock);
143 return (has_qual_exports_list() || is_exported_allUnnamed());
144 }
145 // Returns true if there are any explicit qualified exports. Note that even
146 // if the _qualified_exports list is now empty (because the modules that were
147 // on the list got gc-ed and deleted from the list) this method may still
148 // return true.
149 bool has_qual_exports_list() const {
150 assert_locked_or_safepoint(Module_lock);
151 return (!is_unqual_exported() && _qualified_exports != NULL);
152 }
153 bool is_exported_allUnnamed() const {
154 assert_locked_or_safepoint(Module_lock);
155 return (module()->is_open() || _export_flags == PKG_EXP_ALLUNNAMED);
156 }
157 bool is_unqual_exported() const {
158 assert_locked_or_safepoint(Module_lock);
159 return (module()->is_open() || _export_flags == PKG_EXP_UNQUALIFIED);
160 }
161
162 // Explicitly set _export_flags to PKG_EXP_UNQUALIFIED and clear
163 // PKG_EXP_ALLUNNAMED, if it was set.
164 void set_unqual_exported() {
165 if (module()->is_open()) {
166 // No-op for open modules since all packages are unqualifiedly exported
167 return;
168 }
169 assert(Module_lock->owned_by_self(), "should have the Module_lock");
170 _export_flags = PKG_EXP_UNQUALIFIED;
171 }
172
173 bool exported_pending_delete() const;
174
175 void set_exported(ModuleEntry* m);
176
177 void set_is_exported_allUnnamed();
178
179 void set_classpath_index(s2 classpath_index) {
180 _classpath_index = classpath_index;
181 }
182 s2 classpath_index() const { return _classpath_index; }
183
184 bool has_loaded_class() const { return _classpath_index != -1; }
185
186 // returns true if the package is defined in the unnamed module
187 bool in_unnamed_module() const { return !_module->is_named(); }
188
189 // returns true if the package specifies m as a qualified export, including through an unnamed export
190 bool is_qexported_to(ModuleEntry* m) const;
191
192 // add the module to the package's qualified exports
193 void add_qexport(ModuleEntry* m);
194 void set_export_walk_required(ClassLoaderData* m_loader_data);
195
196 PackageEntry* next() const {
197 return (PackageEntry*)HashtableEntry<Symbol*, mtModule>::next();
198 }
199
200 PackageEntry** next_addr() {
201 return (PackageEntry**)HashtableEntry<Symbol*, mtModule>::next_addr();
202 }
203
204 // iteration of qualified exports
205 void package_exports_do(ModuleClosure* f);
206
207 JFR_ONLY(DEFINE_TRACE_ID_METHODS;)
208
209 // Purge dead weak references out of exported list when any given class loader is unloaded.
210 void purge_qualified_exports();
211 void delete_qualified_exports();
212
213 void print(outputStream* st = tty);
214 void verify();
215 };
216
217 // The PackageEntryTable is a Hashtable containing a list of all packages defined
218 // by a particular class loader. Each package is represented as a PackageEntry node.
219 // The PackageEntryTable's lookup is lock free.
220 //
221 class PackageEntryTable : public Hashtable<Symbol*, mtModule> {
222 friend class VMStructs;
223 public:
224 enum Constants {
225 _packagetable_entry_size = 109 // number of entries in package entry table
226 };
227
228 private:
229 PackageEntry* new_entry(unsigned int hash, Symbol* name, ModuleEntry* module);
230 void add_entry(int index, PackageEntry* new_entry);
231
232 int entry_size() const { return BasicHashtable<mtModule>::entry_size(); }
233
234 PackageEntry** bucket_addr(int i) {
235 return (PackageEntry**)Hashtable<Symbol*, mtModule>::bucket_addr(i);
236 }
237
238 static unsigned int compute_hash(Symbol* name) { return (unsigned int)(name->identity_hash()); }
239 int index_for(Symbol* name) const { return hash_to_index(compute_hash(name)); }
240
241 public:
242 PackageEntryTable(int table_size);
243 ~PackageEntryTable();
244
245 PackageEntry* bucket(int i) {
246 return (PackageEntry*)Hashtable<Symbol*, mtModule>::bucket(i);
247 }
248
249 // Create package in loader's package entry table and return the entry.
250 // If entry already exists, return null. Assume Module lock was taken by caller.
251 PackageEntry* locked_create_entry_or_null(Symbol* name, ModuleEntry* module);
252
253 // lookup Package with loader's package entry table, if not found add
254 PackageEntry* lookup(Symbol* name, ModuleEntry* module);
255
256 // Only lookup Package within loader's package entry table.
257 PackageEntry* lookup_only(Symbol* Package);
258
259 void verify_javabase_packages(GrowableArray<Symbol*> *pkg_list);
260
261 // purge dead weak references out of exported list
262 void purge_all_package_exports();
263
264 void print(outputStream* st = tty);
265 void verify();
266 };
267
268 #endif // SHARE_VM_CLASSFILE_PACKAGEENTRY_HPP
--- EOF ---