if (instanceType != TypeFrame.getNullType()) { if (!(instanceType instanceof ObjectType)) throw new AnalysisException("Field accessed through non-object reference " + instanceType, methodGen, handle); ObjectType objType = (ObjectType) instanceType;
if (instanceType != TypeFrame.getNullType()) { if (!(instanceType instanceof ObjectType)) { throw new AnalysisException("Field accessed through non-object reference " + instanceType, methodGen, handle); } ObjectType objType = (ObjectType) instanceType;
			public void visitLocation(Location location) throws CFGBuilderException, DataflowAnalysisException {				try {					Instruction ins = location.getHandle().getInstruction();					XField xfield = null;					boolean isWrite = false;					boolean isLocal = false;					if (ins instanceof FieldInstruction) {						FieldInstruction fins = (FieldInstruction) ins;						xfield = Lookup.findXField(fins, cpg);						isWrite = ins.getOpcode() == Constants.PUTFIELD;						isLocal = fins.getClassName(cpg).equals(classContext.getJavaClass().getClassName());						if (DEBUG) System.out.println("Handling field access: " + location.getHandle() +							" (frame=" + vnaDataflow.getFactAtLocation(location) + ")");					} else if (ins instanceof INVOKESTATIC) {						INVOKESTATIC inv = (INVOKESTATIC) ins;						InnerClassAccess access = icam.getInnerClassAccess(inv, cpg);						if (access != null && access.getMethodSignature().equals(inv.getSignature(cpg))) {							xfield = access.getField();							isWrite = !access.isLoad();							isLocal = false;							if (DEBUG) System.out.println("Handling inner class access: " + location.getHandle() +								" (frame=" + vnaDataflow.getFactAtLocation(location) + ")");						}					}					// We only care about mutable nonvolatile nonpublic instance fields.					if (xfield != null &&						!(xfield.isStatic() || xfield.isPublic() || xfield.isVolatile() || xfield.isFinal())) {						ValueNumberFrame frame = vnaDataflow.getFactAtLocation(location);						ValueNumber thisValue = !method.isStatic() ? vnaDataflow.getAnalysis().getThisValue() : null;						LockSet lockSet = lockDataflow.getFactAtLocation(location);						InstructionHandle handle = location.getHandle();										// Is the instance locked?						// We consider the access to be locked if either						//   - the object is explicitly locked, or						//   - the field is accessed through the "this" reference,						//     and the method is in the locked method set, or						//   - any value returned by a called method is locked;						//     the (conservative) assumption is that the return lock object						//     is correct for synchronizing the access						ValueNumber instance = frame.getInstance(handle.getInstruction(), cpg);						boolean isExplicitlyLocked = lockSet.getLockCount(instance.getNumber()) > 0;						boolean isAccessedThroughThis = thisValue != null && thisValue.equals(instance);						boolean isLocked = isExplicitlyLocked							|| (lockedMethodSet.contains(method) && isAccessedThroughThis)							|| lockSet.containsReturnValue(vnaDataflow.getAnalysis().getFactory());						// Adjust the field so its class name is the same						// as the type of reference it is accessed through.						// This helps fix false positives produced when a						// threadsafe class is extended by a subclass that						// doesn't care about thread safety.						if (ADJUST_SUBCLASS_ACCESSES) {							// Find the type of the object instance							TypeDataflow typeDataflow = classContext.getTypeDataflow(method);							TypeFrame typeFrame = typeDataflow.getFactAtLocation(location);							Type instanceType = typeFrame.getInstance(handle.getInstruction(), cpg);							// Note: instance type can be Null,							// in which case we won't adjust the field type.							if (instanceType != TypeFrame.getNullType()) {								if (!(instanceType instanceof ObjectType))									throw new AnalysisException("Field accessed through non-object reference " + instanceType,										methodGen, handle);								ObjectType objType = (ObjectType) instanceType;									// If instance class name is not the same as that of the field,								// make it so								String instanceClassName = objType.getClassName();								if (!instanceClassName.equals(xfield.getClassName())) {									xfield = new InstanceField(										instanceClassName,										xfield.getFieldName(),										xfield.getFieldSignature(),										xfield.getAccessFlags()									);								}							}						}										int kind = 0;						kind |= isLocked ? LOCKED : UNLOCKED;						kind |= isWrite ? WRITE : READ;										if (DEBUG) System.out.println("IS2:\t" +							SignatureConverter.convertMethodSignature(classContext.getMethodGen(method)) +							"\t" + xfield + "\t" + ((isWrite ? "W" : "R") + "/" + (isLocked ? "L" : "U")));										FieldStats stats = getStats(xfield);						stats.addAccess(kind);										if (isExplicitlyLocked && isLocal)							stats.addLocalLock();						if (isGetterMethod && !isLocked)							stats.addGetterMethodAccess();										stats.addAccess(classContext, method, handle, isLocked);					}					// FIXME: should we do something for static fields?				} catch (ClassNotFoundException e) {					bugReporter.reportMissingClass(e);				}			}