2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
6 * The Java Pathfinder core (jpf-core) platform is licensed under the
7 * Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0.
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package gov.nasa.jpf.vm;
20 import gov.nasa.jpf.Config;
21 import gov.nasa.jpf.JPF;
22 import gov.nasa.jpf.util.JPFLogger;
25 import java.util.ArrayList;
26 import java.util.List;
29 * @author Nastaran Shafiei <nastaran.shafiei@gmail.com>
31 * Represents the JPF system classloader which models the following hierarchy.
45 * Since in the standard VM user does not have any control over the built-in
46 * classloaders hierarchy, in JPF, we model all three by an instance of
47 * SystemClassLoader which is responsible to load classes from Java API,
48 * standard extensions packages, and the local file system.
50 public abstract class SystemClassLoaderInfo extends ClassLoaderInfo {
52 static JPFLogger log = JPF.getLogger("class");
54 // we need to keep track of this in case something needs the current SystemClassLoaderInfo before we have a main thread
55 static SystemClassLoaderInfo lastInstance;
57 // note that initialization requires these to be startup classes
58 protected ClassInfo classLoaderClassInfo;
59 protected ClassInfo objectClassInfo;
60 protected ClassInfo classClassInfo;
61 protected ClassInfo stringClassInfo;
62 protected ClassInfo weakRefClassInfo;
63 protected ClassInfo refClassInfo;
64 protected ClassInfo enumClassInfo;
65 protected ClassInfo threadClassInfo;
66 protected ClassInfo threadGroupClassInfo;
67 protected ClassInfo charArrayClassInfo;
69 protected int unCachedClasses = 10;
72 * list of configurable Attributors for ClassInfos, MethodInfos and FieldInfos
73 * that are consulted after creating the ClassInfo but before notifying classLoaded() listeners
75 protected List<Attributor> attributors;
78 public SystemClassLoaderInfo (VM vm, int appId){
83 // this is a hack - for user ClassLoaderInfos, we compute the id from the corresponding
84 // objRef of the JPF ClassLoader object. For SystemClassLoaderInfos we can't do that because
85 // they are created before we can create JPF objects. However, this is safe if we know
86 // the provided id is never going to be the objRef of a future ClassLoader object, which is
87 // a safe bet since the first objects created are all system Class objects that are never going to
89 this.id = computeId(appId);
91 initializeSystemClassPath( vm, appId);
92 initializeAttributors( vm, appId);
95 protected abstract void initializeSystemClassPath (VM vm, int appId);
97 protected void initializeAttributors (VM vm, int appId){
98 attributors = new ArrayList<Attributor>();
100 Config conf = vm.getConfig();
101 String key = conf.getIndexableKey("vm.attributors", appId);
103 for (Attributor a : conf.getInstances(key, Attributor.class)){
109 public void addAttributor (Attributor a){
114 * to be called on each ClassInfo created in the realm of this SystemClassLoader
117 protected void setAttributes (ClassInfo ci){
118 for (Attributor a: attributors){
123 //--- these can be used to build the app specific system CP
124 protected File[] getPathElements (Config conf, String keyBase, int appId) {
125 File[] pathElements = null;
127 // try appId indexed key first
128 String key = keyBase + '.' + appId;
129 if (conf.containsKey(key)) {
130 pathElements = conf.getPathArray(key);
132 } else { // fall back to keyBase
133 pathElements = conf.getPathArray(keyBase);
140 public SystemClassLoaderInfo getSystemClassLoader() {
146 public ClassInfo getResolvedClassInfo (String clsName){
147 ClassInfo ci = super.getResolvedClassInfo(clsName);
149 if (unCachedClasses > 0){
150 updateCachedClassInfos(ci);
157 public boolean isSystemClassLoader() {
161 static boolean checkClassName (String clsName) {
162 if ( !clsName.matches("[a-zA-Z_$][a-zA-Z_$0-9.]*")) {
166 // well, those two could be part of valid class names, but
167 // in all likeliness somebody specified a filename instead of
169 if (clsName.endsWith(".java")) {
172 if (clsName.endsWith(".class")) {
181 public ClassInfo loadClass(String cname) {
182 return getResolvedClassInfo(cname);
186 protected ClassInfo loadSystemClass (String typeName){
187 return new ClassInfo( typeName, this);
190 protected void setClassLoaderObject (ElementInfo ei){
191 objRef = ei.getObjectRef();
192 //id = computeId(objRef);
195 ei.setIntField(ID_FIELD, id);
199 //-- ClassInfos cache management --
201 protected void updateCachedClassInfos (ClassInfo ci) {
202 String name = ci.name;
204 if ((objectClassInfo == null) && name.equals("java.lang.Object")) {
205 objectClassInfo = ci; unCachedClasses--;
206 } else if ((classClassInfo == null) && name.equals("java.lang.Class")) {
207 classClassInfo = ci; unCachedClasses--;
208 } else if ((classLoaderClassInfo == null) && name.equals("java.lang.ClassLoader")) {
210 classLoaderClassInfo = ci; unCachedClasses--;
211 } else if ((stringClassInfo == null) && name.equals("java.lang.String")) {
212 stringClassInfo = ci; unCachedClasses--;
213 } else if ((charArrayClassInfo == null) && name.equals("[C")) {
214 charArrayClassInfo = ci; unCachedClasses--;
215 } else if ((weakRefClassInfo == null) && name.equals("java.lang.ref.WeakReference")) {
216 weakRefClassInfo = ci; unCachedClasses--;
217 } else if ((refClassInfo == null) && name.equals("java.lang.ref.Reference")) {
218 refClassInfo = ci; unCachedClasses--;
219 } else if ((enumClassInfo == null) && name.equals("java.lang.Enum")) {
220 enumClassInfo = ci; unCachedClasses--;
221 } else if ((threadClassInfo == null) && name.equals("java.lang.Thread")) {
222 threadClassInfo = ci; unCachedClasses--;
223 } else if ((threadGroupClassInfo == null) && name.equals("java.lang.ThreadGroup")) {
224 threadGroupClassInfo = ci; unCachedClasses--;
228 protected ClassInfo getObjectClassInfo() {
229 return objectClassInfo;
232 protected ClassInfo getClassClassInfo() {
233 return classClassInfo;
236 protected ClassInfo getClassLoaderClassInfo() {
237 return classLoaderClassInfo;
240 protected ClassInfo getStringClassInfo() {
241 return stringClassInfo;
244 protected ClassInfo getCharArrayClassInfo() {
245 return charArrayClassInfo;
248 protected ClassInfo getEnumClassInfo() {
249 return enumClassInfo;
252 protected ClassInfo getThreadClassInfo() {
253 return threadClassInfo;
256 protected ClassInfo getThreadGroupClassInfo() {
257 return threadGroupClassInfo;
260 protected ClassInfo getReferenceClassInfo() {
264 protected ClassInfo getWeakReferenceClassInfo() {
265 return weakRefClassInfo;