⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serializableidiom.java

📁 A static analysis tool to find bugs in Java programs
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
					implementsSerializableDirectly|| seenTransientField ? HIGH_PRIORITY : 						( sawSerialVersionUID ?  NORMAL_PRIORITY : LOW_PRIORITY))					.addClass(getThisClass().getClassName()));		// Downgrade class-level warnings if it's a GUI class.		int priority = false && isGUIClass ? LOW_PRIORITY : NORMAL_PRIORITY;		if (obj.getClassName().endsWith("_Stub")) priority++;		if (isExternalizable && !hasPublicVoidConstructor && !isAbstract)			bugReporter.reportBug(new BugInstance(this, "SE_NO_SUITABLE_CONSTRUCTOR_FOR_EXTERNALIZATION",					directlyImplementsExternalizable ?					HIGH_PRIORITY : NORMAL_PRIORITY)					.addClass(getThisClass().getClassName()));		if (!foundSynthetic) priority++;		if (seenTransientField) priority--;		if (!isAnonymousInnerClass 			&& !isExternalizable && !isGUIClass && !obj.isAbstract()				&& isSerializable && !isAbstract && !sawSerialVersionUID)			bugReporter.reportBug(new BugInstance(this, "SE_NO_SERIALVERSIONID", priority).addClass(this));		if (writeObjectIsSynchronized && !foundSynchronizedMethods)			bugReporter.reportBug(new BugInstance(this, "WS_WRITEOBJECT_SYNC", LOW_PRIORITY).addClass(this));	}	@Override		 public void visit(Method obj) {		int accessFlags = obj.getAccessFlags();		boolean isSynchronized = (accessFlags & ACC_SYNCHRONIZED) != 0;		if (getMethodName().equals("<init>") && getMethodSig().equals("()V")				&& (accessFlags & ACC_PUBLIC) != 0		)			hasPublicVoidConstructor = true;		if (!getMethodName().equals("<init>")				&& isSynthetic(obj))			foundSynthetic = true;		// System.out.println(methodName + isSynchronized);		if (getMethodName().equals("readExternal")				&& getMethodSig().equals("(Ljava/io/ObjectInput;)V")) {			sawReadExternal = true;			if (false && !obj.isPrivate())				System.out.println("Non-private readExternal method in: " + getDottedClassName());		} else if (getMethodName().equals("writeExternal")				&& getMethodSig().equals("(Ljava/io/Objectoutput;)V")) {			sawWriteExternal = true;			if (false && !obj.isPrivate())				System.out.println("Non-private writeExternal method in: " + getDottedClassName());		}		else if (getMethodName().equals("readResolve")				&& getMethodSig().startsWith("()")				&& isSerializable) {			sawReadResolve = true;			if (!getMethodSig().equals("()Ljava/lang/Object;"))				bugReporter.reportBug(new BugInstance(this, "SE_READ_RESOLVE_MUST_RETURN_OBJECT", HIGH_PRIORITY)						.addClassAndMethod(this));		}else if (getMethodName().equals("readObject")				&& getMethodSig().equals("(Ljava/io/ObjectInputStream;)V")				&& isSerializable) {			sawReadObject = true;			if (!obj.isPrivate())				bugReporter.reportBug(new BugInstance(this, "SE_METHOD_MUST_BE_PRIVATE", HIGH_PRIORITY)						.addClassAndMethod(this));		} else if (getMethodName().equals("readObjectNoData")				&& getMethodSig().equals("()V")				&& isSerializable) {			if (!obj.isPrivate())				bugReporter.reportBug(new BugInstance(this, "SE_METHOD_MUST_BE_PRIVATE", HIGH_PRIORITY)						.addClassAndMethod(this));		}else if (getMethodName().equals("writeObject")				&& getMethodSig().equals("(Ljava/io/ObjectOutputStream;)V")				&& isSerializable) {			sawReadObject = true;			if (!obj.isPrivate())				bugReporter.reportBug(new BugInstance(this, "SE_METHOD_MUST_BE_PRIVATE", HIGH_PRIORITY)						.addClassAndMethod(this));		}		if (isSynchronized) {		if (getMethodName().equals("readObject") &&				getMethodSig().equals("(Ljava/io/ObjectInputStream;)V") &&				isSerializable)			bugReporter.reportBug(new BugInstance(this, "RS_READOBJECT_SYNC", NORMAL_PRIORITY).addClass(this));		else if (getMethodName().equals("writeObject")				&& getMethodSig().equals("(Ljava/io/ObjectOutputStream;)V")				&& isSerializable)			writeObjectIsSynchronized = true;		else			foundSynchronizedMethods = true;		}		super.visit(obj);	}	boolean isSynthetic(FieldOrMethod obj) {		Attribute[] a = obj.getAttributes();		for (Attribute aA : a)			if (aA instanceof Synthetic) return true;		return false;	}	@Override		 public void visit(Code obj) {		if (isSerializable) {			stack.resetForMethodEntry(this);			super.visit(obj);		}	}	@Override	public void sawOpcode(int seen) {		stack.mergeJumps(this);		if (seen == PUTFIELD) {			String nameOfClass = getClassConstantOperand();			if ( getClassName().equals(nameOfClass))  {				Item first = stack.getStackItem(0);				boolean isPutOfDefaultValue = first.isNull() || first.isInitialParameter();				if (!isPutOfDefaultValue && first.getConstant() != null) {					Object constant = first.getConstant();					if (constant instanceof Number && ((Number)constant).intValue() == 0 							|| constant.equals(Boolean.FALSE))						isPutOfDefaultValue = true;				}				if (!isPutOfDefaultValue) {					String nameOfField = getNameConstantOperand();					if (transientFieldsUpdates.containsKey(nameOfField) ) {						if (getMethodName().equals("<init>")) transientFieldsSetInConstructor.add(nameOfField);						else transientFieldsUpdates.put(nameOfField, transientFieldsUpdates.get(nameOfField)+1);					} else if (fieldsThatMightBeAProblem.containsKey(nameOfField)) {						try {							JavaClass classStored = first.getJavaClass();							double isSerializable = DeepSubtypeAnalysis							.isDeepSerializable(classStored);							if (isSerializable <= 0.2) {								XField f = fieldsThatMightBeAProblem.get(nameOfField);								String sig = f.getSignature();								// System.out.println("Field signature: " + sig);								// System.out.println("Class stored: " +								// classStored.getClassName());								String genSig = "L"									+ classStored.getClassName().replace('.', '/')									+ ";";								if (!sig.equals(genSig)) {									double bias = 0.0;									if (!getMethodName().equals("<init>")) bias = 1.0;									int priority = computePriority(isSerializable, bias);									fieldWarningList.add(new BugInstance(this,											"SE_BAD_FIELD_STORE", priority).addClass(													getThisClass().getClassName()).addField(f)													.addType(genSig).describe("TYPE_FOUND").addSourceLine(this));								}							}						} catch (Exception e) {							// ignore it						}					}				}			}		}		stack.sawOpcode(this,seen);	}	private OpcodeStack stack = new OpcodeStack();	@Override	public void visit(Field obj) {		int flags = obj.getAccessFlags();		if (obj.isTransient()) {			if (isSerializable) {				seenTransientField = true;				transientFields.put(obj.getName(), XFactory.createXField(this));				transientFieldsUpdates.put(obj.getName(), 0);			} else if (reportTransientFieldOfNonSerializableClass) {				bugReporter.reportBug(new BugInstance(this, "SE_TRANSIENT_FIELD_OF_NONSERIALIZABLE_CLASS", NORMAL_PRIORITY)				.addClass(this)				.addVisitedField(this));			}		}		else if (getClassName().indexOf("ObjectStreamClass") == -1				&& isSerializable				&& !isExternalizable				&& getFieldSig().indexOf("L") >= 0 && !obj.isTransient() && !obj.isStatic()) {			try {				double isSerializable = DeepSubtypeAnalysis.isDeepSerializable(getFieldSig());				if (isSerializable < 1.0)					fieldsThatMightBeAProblem.put(obj.getName(), XFactory.createXField(this));				if (isSerializable < 0.9) {					// Priority is LOW for GUI classes (unless explicitly marked Serializable),					// HIGH if the class directly implements Serializable,					// NORMAL otherwise.					int priority = computePriority(isSerializable, 0);					if (priority > NORMAL_PRIORITY							&& obj.getName().startsWith("this$"))							priority = NORMAL_PRIORITY;					else if (innerClassHasOuterInstance) {						if (isAnonymousInnerClass) priority+=2;						else priority+=1;					}					if (false)					System.out.println("SE_BAD_FIELD: " + getThisClass().getClassName()						+" " +  obj.getName()							+" " +  isSerializable						+" " +  implementsSerializableDirectly						+" " +  sawSerialVersionUID						+" " +  isGUIClass);					// Report is queued until after the entire class has been seen.					if (obj.getName().equals("this$0"))						fieldWarningList.add(new BugInstance(this, "SE_BAD_FIELD_INNER_CLASS", priority)							.addClass(getThisClass().getClassName()));						else if (isSerializable < 0.9) fieldWarningList.add(new BugInstance(this, "SE_BAD_FIELD", priority)							.addClass(getThisClass().getClassName())							.addField(getDottedClassName(), obj.getName(), getFieldSig(), false));				} else if (false && obj.getName().equals("this$0"))					fieldWarningList.add(new BugInstance(this, "SE_INNER_CLASS",							implementsSerializableDirectly ? NORMAL_PRIORITY : LOW_PRIORITY)					.addClass(getThisClass().getClassName()));			} catch (ClassNotFoundException e) {				bugReporter.reportMissingClass(e);			}		}		if (!getFieldName().startsWith("this")				&& isSynthetic(obj))			foundSynthetic = true;		if (!getFieldName().equals("serialVersionUID")) return;		int mask = ACC_STATIC | ACC_FINAL;		if (!getFieldSig().equals("I")				&& !getFieldSig().equals("J"))			return;		if ((flags & mask) == mask				&& getFieldSig().equals("I")) {			bugReporter.reportBug(new BugInstance(this, "SE_NONLONG_SERIALVERSIONID", LOW_PRIORITY)					.addClass(this)					.addVisitedField(this));			sawSerialVersionUID = true;			return;		} else if ((flags & ACC_STATIC) == 0) {			bugReporter.reportBug(new BugInstance(this, "SE_NONSTATIC_SERIALVERSIONID", NORMAL_PRIORITY)					.addClass(this)					.addVisitedField(this));			return;		} else if ((flags & ACC_FINAL) == 0) {			bugReporter.reportBug(new BugInstance(this, "SE_NONFINAL_SERIALVERSIONID", NORMAL_PRIORITY)					.addClass(this)					.addVisitedField(this));			return;		}		sawSerialVersionUID = true;	}	private int computePriority(double isSerializable, double bias) {		int priority = (int)(1.9+isSerializable*3 + bias);		if (implementsSerializableDirectly || sawSerialVersionUID || sawReadObject)			priority--;		if (!implementsSerializableDirectly && priority == HIGH_PRIORITY)			priority = NORMAL_PRIORITY;		return priority;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -