pax_global_header00006660000000000000000000000064120731042750014513gustar00rootroot0000000000000052 comment=c26b6c6ded6b739746741ff5c57020397fce7cf7 libasm4-java-4.1/000077500000000000000000000000001207310427500136315ustar00rootroot00000000000000libasm4-java-4.1/.classpath000066400000000000000000000042751207310427500156240ustar00rootroot00000000000000 libasm4-java-4.1/.fbprefs000066400000000000000000000216061207310427500152660ustar00rootroot00000000000000#FindBugs User Preferences #Mon Aug 01 18:36:02 CEST 2011 detectorAppendingToAnObjectOutputStream=AppendingToAnObjectOutputStream|true detectorBCPMethodReturnCheck=BCPMethodReturnCheck|false detectorBadAppletConstructor=BadAppletConstructor|false detectorBadResultSetAccess=BadResultSetAccess|false detectorBadSyntaxForRegularExpression=BadSyntaxForRegularExpression|true detectorBadUseOfReturnValue=BadUseOfReturnValue|true detectorBadlyOverriddenAdapter=BadlyOverriddenAdapter|true detectorBooleanReturnNull=BooleanReturnNull|true detectorBuildInterproceduralCallGraph=BuildInterproceduralCallGraph|false detectorBuildObligationPolicyDatabase=BuildObligationPolicyDatabase|true detectorCallToUnsupportedMethod=CallToUnsupportedMethod|true detectorCalledMethods=CalledMethods|true detectorCheckCalls=CheckCalls|false detectorCheckExpectedWarnings=CheckExpectedWarnings|false detectorCheckImmutableAnnotation=CheckImmutableAnnotation|true detectorCheckTypeQualifiers=CheckTypeQualifiers|true detectorCloneIdiom=CloneIdiom|true detectorComparatorIdiom=ComparatorIdiom|false detectorConfusedInheritance=ConfusedInheritance|true detectorConfusionBetweenInheritedAndOuterMethod=ConfusionBetweenInheritedAndOuterMethod|true detectorCrossSiteScripting=CrossSiteScripting|true detectorDoInsideDoPrivileged=DoInsideDoPrivileged|true detectorDontCatchIllegalMonitorStateException=DontCatchIllegalMonitorStateException|true detectorDontIgnoreResultOfPutIfAbsent=DontIgnoreResultOfPutIfAbsent|true detectorDontUseEnum=DontUseEnum|true detectorDroppedException=DroppedException|true detectorDumbMethodInvocations=DumbMethodInvocations|true detectorDumbMethods=DumbMethods|true detectorDuplicateBranches=DuplicateBranches|true detectorEmptyZipFileEntry=EmptyZipFileEntry|true detectorEqStringTest=EqStringTest|false detectorEqualsOperandShouldHaveClassCompatibleWithThis=EqualsOperandShouldHaveClassCompatibleWithThis|true detectorFieldItemSummary=FieldItemSummary|true detectorFinalizerNullsFields=FinalizerNullsFields|true detectorFindBadCast=FindBadCast|false detectorFindBadCast2=FindBadCast2|true detectorFindBadEqualsImplementation=FindBadEqualsImplementation|false detectorFindBadForLoop=FindBadForLoop|true detectorFindBugsSummaryStats=FindBugsSummaryStats|true detectorFindCircularDependencies=FindCircularDependencies|false detectorFindDeadLocalStores=FindDeadLocalStores|true detectorFindDoubleCheck=FindDoubleCheck|true detectorFindEmptySynchronizedBlock=FindEmptySynchronizedBlock|true detectorFindFieldSelfAssignment=FindFieldSelfAssignment|true detectorFindFinalizeInvocations=FindFinalizeInvocations|true detectorFindFloatEquality=FindFloatEquality|true detectorFindFloatMath=FindFloatMath|false detectorFindHEmismatch=FindHEmismatch|true detectorFindInconsistentSync2=FindInconsistentSync2|true detectorFindJSR166LockMonitorenter=FindJSR166LockMonitorenter|true detectorFindLocalSelfAssignment2=FindLocalSelfAssignment2|true detectorFindMaskedFields=FindMaskedFields|true detectorFindMismatchedWaitOrNotify=FindMismatchedWaitOrNotify|true detectorFindNakedNotify=FindNakedNotify|true detectorFindNonSerializableStoreIntoSession=FindNonSerializableStoreIntoSession|false detectorFindNonSerializableValuePassedToWriteObject=FindNonSerializableValuePassedToWriteObject|true detectorFindNonShortCircuit=FindNonShortCircuit|true detectorFindNullDeref=FindNullDeref|true detectorFindNullDerefsInvolvingNonShortCircuitEvaluation=FindNullDerefsInvolvingNonShortCircuitEvaluation|true detectorFindOpenStream=FindOpenStream|true detectorFindPuzzlers=FindPuzzlers|true detectorFindRefComparison=FindRefComparison|true detectorFindReturnRef=FindReturnRef|false detectorFindRunInvocations=FindRunInvocations|true detectorFindSelfComparison=FindSelfComparison|true detectorFindSelfComparison2=FindSelfComparison2|true detectorFindSleepWithLockHeld=FindSleepWithLockHeld|true detectorFindSpinLoop=FindSpinLoop|true detectorFindSqlInjection=FindSqlInjection|false detectorFindTwoLockWait=FindTwoLockWait|true detectorFindUncalledPrivateMethods=FindUncalledPrivateMethods|true detectorFindUnconditionalWait=FindUnconditionalWait|true detectorFindUninitializedGet=FindUninitializedGet|true detectorFindUnrelatedTypesInGenericContainer=FindUnrelatedTypesInGenericContainer|true detectorFindUnreleasedLock=FindUnreleasedLock|true detectorFindUnsatisfiedObligation=FindUnsatisfiedObligation|true detectorFindUnsyncGet=FindUnsyncGet|true detectorFindUselessControlFlow=FindUselessControlFlow|true detectorFormatStringChecker=FormatStringChecker|true detectorHugeSharedStringConstants=HugeSharedStringConstants|true detectorIDivResultCastToDouble=IDivResultCastToDouble|true detectorIncompatMask=IncompatMask|true detectorInconsistentAnnotations=InconsistentAnnotations|true detectorInefficientMemberAccess=InefficientMemberAccess|false detectorInefficientToArray=InefficientToArray|true detectorInfiniteLoop=InfiniteLoop|true detectorInfiniteRecursiveLoop=InfiniteRecursiveLoop|true detectorInfiniteRecursiveLoop2=InfiniteRecursiveLoop2|false detectorInheritanceUnsafeGetResource=InheritanceUnsafeGetResource|true detectorInitializationChain=InitializationChain|true detectorInstantiateStaticClass=InstantiateStaticClass|true detectorInvalidJUnitTest=InvalidJUnitTest|true detectorIteratorIdioms=IteratorIdioms|true detectorLazyInit=LazyInit|true detectorLoadOfKnownNullValue=LoadOfKnownNullValue|true detectorLockedFields=LockedFields|false detectorLostLoggerDueToWeakReference=LostLoggerDueToWeakReference|true detectorMethodReturnCheck=MethodReturnCheck|true detectorMethods=Methods|true detectorMultithreadedInstanceAccess=MultithreadedInstanceAccess|true detectorMutableLock=MutableLock|true detectorMutableStaticFields=MutableStaticFields|false detectorNaming=Naming|true detectorNoteAnnotationRetention=NoteAnnotationRetention|true detectorNoteCheckReturnValue=NoteCheckReturnValue|true detectorNoteCheckReturnValueAnnotations=NoteCheckReturnValueAnnotations|true detectorNoteDirectlyRelevantTypeQualifiers=NoteDirectlyRelevantTypeQualifiers|true detectorNoteJCIPAnnotation=NoteJCIPAnnotation|true detectorNoteNonNullAnnotations=NoteNonNullAnnotations|true detectorNoteNonnullReturnValues=NoteNonnullReturnValues|true detectorNoteSuppressedWarnings=NoteSuppressedWarnings|true detectorNoteUnconditionalParamDerefs=NoteUnconditionalParamDerefs|true detectorNumberConstructor=NumberConstructor|false detectorOverridingEqualsNotSymmetrical=OverridingEqualsNotSymmetrical|true detectorPreferZeroLengthArrays=PreferZeroLengthArrays|true detectorPublicSemaphores=PublicSemaphores|true detectorQuestionableBooleanAssignment=QuestionableBooleanAssignment|true detectorReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass=ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass|true detectorReadReturnShouldBeChecked=ReadReturnShouldBeChecked|true detectorRedundantInterfaces=RedundantInterfaces|true detectorReflectiveClasses=ReflectiveClasses|true detectorRepeatedConditionals=RepeatedConditionals|true detectorResolveAllReferences=ResolveAllReferences|false detectorRuntimeExceptionCapture=RuntimeExceptionCapture|true detectorSerializableIdiom=SerializableIdiom|false detectorStartInConstructor=StartInConstructor|true detectorStaticCalendarDetector=StaticCalendarDetector|true detectorStringConcatenation=StringConcatenation|true detectorSuperfluousInstanceOf=SuperfluousInstanceOf|true detectorSuspiciousThreadInterrupted=SuspiciousThreadInterrupted|true detectorSwitchFallthrough=SwitchFallthrough|true detectorSynchronizationOnSharedBuiltinConstant=SynchronizationOnSharedBuiltinConstant|true detectorSynchronizeAndNullCheckField=SynchronizeAndNullCheckField|true detectorSynchronizeOnClassLiteralNotGetClass=SynchronizeOnClassLiteralNotGetClass|true detectorSynchronizingOnContentsOfFieldToProtectField=SynchronizingOnContentsOfFieldToProtectField|true detectorTestASM=TestASM|false detectorTestDataflowAnalysis=TestDataflowAnalysis|false detectorTestingGround=TestingGround|false detectorTrainFieldStoreTypes=TrainFieldStoreTypes|true detectorTrainNonNullAnnotations=TrainNonNullAnnotations|true detectorTrainUnconditionalDerefParams=TrainUnconditionalDerefParams|true detectorURLProblems=URLProblems|true detectorUncallableMethodOfAnonymousClass=UncallableMethodOfAnonymousClass|true detectorUnnecessaryMath=UnnecessaryMath|true detectorUnreadFields=UnreadFields|true detectorUseObjectEquals=UseObjectEquals|true detectorUselessSubclassMethod=UselessSubclassMethod|true detectorVarArgsProblems=VarArgsProblems|true detectorVolatileUsage=VolatileUsage|true detectorWaitInLoop=WaitInLoop|true detectorWrongMapIterator=WrongMapIterator|true detectorXMLFactoryBypass=XMLFactoryBypass|true detector_threshold=2 effort=max excludefilter0=findbugsExclude.xml filter_settings=Medium|BAD_PRACTICE,CORRECTNESS,EXPERIMENTAL,I18N,MALICIOUS_CODE,MT_CORRECTNESS,PERFORMANCE,SECURITY,STYLE|false filter_settings_neg=NOISE| run_at_full_build=false libasm4-java-4.1/.project000066400000000000000000000011141207310427500152750ustar00rootroot00000000000000 asm3 org.eclipse.jdt.core.javabuilder edu.umd.cs.findbugs.plugin.eclipse.findbugsBuilder org.eclipse.jdt.core.javanature edu.umd.cs.findbugs.plugin.eclipse.findbugsNature libasm4-java-4.1/.settings/000077500000000000000000000000001207310427500155475ustar00rootroot00000000000000libasm4-java-4.1/.settings/de.loskutov.anyedit.AnyEditTools.prefs000066400000000000000000000007411207310427500251000ustar00rootroot00000000000000#Mon Sep 12 22:02:30 CEST 2011 activeContentFilterList=*.makefile,makefile,*.Makefile,Makefile,Makefile.*,*.mk,MANIFEST.MF addNewLine=false convertActionOnSaave=AnyEdit.CnvrtTabToSpaces eclipse.preferences.version=1 inActiveContentFilterList= javaTabWidthForJava=true org.eclipse.jdt.ui.editor.tab.width=4 projectPropsEnabled=true removeTrailingSpaces=true replaceAllSpaces=false replaceAllTabs=false saveAndAddLine=false saveAndConvert=false saveAndTrim=true useModulo4Tabs=false libasm4-java-4.1/.settings/org.eclipse.jdt.core.prefs000066400000000000000000000712131207310427500225350ustar00rootroot00000000000000#Sat Aug 18 17:43:18 CEST 2012 eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.5 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.autoboxing=ignore org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning org.eclipse.jdt.core.compiler.problem.deadCode=warning org.eclipse.jdt.core.compiler.problem.deprecation=warning org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled org.eclipse.jdt.core.compiler.problem.discouragedReference=warning org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning org.eclipse.jdt.core.compiler.problem.forbiddenReference=error org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore org.eclipse.jdt.core.compiler.problem.nullReference=warning org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=ignore org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore org.eclipse.jdt.core.compiler.problem.unsafeTypeOperation=ignore org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled org.eclipse.jdt.core.compiler.problem.unusedImport=warning org.eclipse.jdt.core.compiler.problem.unusedLabel=warning org.eclipse.jdt.core.compiler.problem.unusedLocal=warning org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=ignore org.eclipse.jdt.core.compiler.source=1.5 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_assignment=0 org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 org.eclipse.jdt.core.formatter.blank_lines_after_package=1 org.eclipse.jdt.core.formatter.blank_lines_before_field=0 org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 org.eclipse.jdt.core.formatter.blank_lines_before_method=1 org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 org.eclipse.jdt.core.formatter.blank_lines_before_package=0 org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false org.eclipse.jdt.core.formatter.comment.format_block_comments=true org.eclipse.jdt.core.formatter.comment.format_comments=true org.eclipse.jdt.core.formatter.comment.format_header=false org.eclipse.jdt.core.formatter.comment.format_html=true org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true org.eclipse.jdt.core.formatter.comment.format_line_comments=true org.eclipse.jdt.core.formatter.comment.format_source_code=true org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true org.eclipse.jdt.core.formatter.comment.indent_root_tags=true org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert org.eclipse.jdt.core.formatter.comment.line_length=80 org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false org.eclipse.jdt.core.formatter.compact_else_if=true org.eclipse.jdt.core.formatter.continuation_indentation=2 org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true org.eclipse.jdt.core.formatter.indent_empty_lines=false org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false org.eclipse.jdt.core.formatter.indentation.size=8 org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.join_lines_in_comments=true org.eclipse.jdt.core.formatter.join_wrapped_lines=true org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false org.eclipse.jdt.core.formatter.lineSplit=80 org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true org.eclipse.jdt.core.formatter.tabulation.char=space org.eclipse.jdt.core.formatter.tabulation.size=4 org.eclipse.jdt.core.formatter.use_on_off_tags=false org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true libasm4-java-4.1/.settings/org.eclipse.jdt.ui.prefs000066400000000000000000000161701207310427500222230ustar00rootroot00000000000000#Sat Aug 18 17:43:18 CEST 2012 comment_clear_blank_lines=false comment_format_comments=true comment_format_header=false comment_format_html=false comment_format_source_code=false comment_indent_parameter_description=false comment_indent_root_tags=true comment_line_length=80 comment_new_line_for_parameter=false comment_separate_root_tags=true eclipse.preferences.version=1 formatter_profile=_Java conventions without tabs formatter_settings_version=12 org.eclipse.jdt.ui.text.custom_code_templates= libasm4-java-4.1/.settings/org.eclipse.mylar.tasklist.prefs000066400000000000000000000002231207310427500237770ustar00rootroot00000000000000#Tue Nov 21 01:22:11 EST 2006 eclipse.preferences.version=1 project.repository.kind=web project.repository.url=http\://forge.objectweb.org/tracker libasm4-java-4.1/LICENSE.txt000066400000000000000000000030761207310427500154620ustar00rootroot00000000000000 ASM: a very small and fast Java bytecode manipulation framework Copyright (c) 2000-2011 INRIA, France Telecom All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. libasm4-java-4.1/README.txt000066400000000000000000000047511207310427500153360ustar00rootroot00000000000000******************************************************************************* * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************* This directory is the base directory of the product. It contains(*) the following items: - archive: ant files to build the jar(s) of the product, - build.properties: properties to configure the build process, - build.xml: main ant file to build the product, - config: external libraries required only for building the product, - doc: documentation of the product, - etc: scripts to run the product, - examples: examples of use of the product, - externals: external libraires required for running the product, - jdoc: ant files to build the javadoc documentation(s) of the product, - sr': sources of the product, - test: tests of the product, - web: source of the web site of the product. (*) some items may not be present, depending on the product. libasm4-java-4.1/archive/000077500000000000000000000000001207310427500152525ustar00rootroot00000000000000libasm4-java-4.1/archive/README.txt000066400000000000000000000052371207310427500167570ustar00rootroot00000000000000******************************************************************************* * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************* This directory contains ant files to build the jars of the product. The following rules describe the convention to write such files: - An ant file must build only one jar file. - The name of the ant file must be the name of the jar it builds: org-foo-bar.xml must build org-foo-bar.jar. - Among the elements which are included into a jar, you must specify a manifest. It is adviced to store the manifest file in this directory. The manifest file can be shared by several jars. The name of the manifest file must be similar to the name of the jar file. - Only the default task is called on each ant file. - The jar file must be produced into the ${dist.lib} directory. Sample ant file: ... libasm4-java-4.1/archive/asm-all.bnd000066400000000000000000000046161207310427500172740ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### Implementation-Title: ASM all classes Implementation-Version: ${product.artifact} Implementation-Vendor: France Telecom R&D Bundle-Name: ASM all classes with debug info Bundle-Vendor: France Telecom R&D Bundle-Version: ${product.artifact} Bundle-DocURL: http://asm.objectweb.org Bundle-SymbolicName: org.objectweb.asm.all Export-Package: \ !org.objectweb.asm.optimizer.*,\ org.objectweb.asm.*;version=${product.artifact} Import-Package: \ javax.xml.transform.*;resolution:="optional",\ org.xml.sax.*;resolution:="optional" Bundle-RequiredExecutionEnvironment: J2SE-1.3 -removeheaders:\ ANNV,\ DSTAMP,\ FRAMESV,\ RESIZEV,\ SIGV,\ TODAY,\ TSTAMP,\ WRITERV libasm4-java-4.1/archive/asm-all.pom000066400000000000000000000037001207310427500173150ustar00rootroot00000000000000 4.0.0 org.ow2.asm asm-parent @product.artifact@ ASM All org.ow2.asm asm-all jar libasm4-java-4.1/archive/asm-all.xml000066400000000000000000000063611207310427500173300ustar00rootroot00000000000000 It is highly recommended to use only the necessary ASM jars for your application instead of using the asm-all jar, unless you really need all ASM packages. libasm4-java-4.1/archive/asm-analysis.bnd000066400000000000000000000046051207310427500203450ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### Implementation-Title: ASM static code analysis framework Implementation-Version: ${product.artifact} Implementation-Vendor: France Telecom R&D Bundle-Name: ASM static code analysis framework Bundle-Vendor: France Telecom R&D Bundle-Version: ${product.artifact} Bundle-DocURL: http://asm.objectweb.org Bundle-SymbolicName: org.objectweb.asm.analysis Export-Package: \ org.objectweb.asm.tree.analysis;version=${product.artifact} Import-Package: \ org.objectweb.asm.*;version:="[${product.artifact},${product.artifact}]" Bundle-RequiredExecutionEnvironment: J2SE-1.3 -removeheaders:\ ANNV,\ DSTAMP,\ FRAMESV,\ RESIZEV,\ SIGV,\ TODAY,\ TSTAMP,\ WRITERV libasm4-java-4.1/archive/asm-analysis.pom000066400000000000000000000040751207310427500203760ustar00rootroot00000000000000 4.0.0 asm-parent org.ow2.asm @product.artifact@ ASM Analysis asm-analysis jar asm-tree org.ow2.asm libasm4-java-4.1/archive/asm-analysis.xml000066400000000000000000000057011207310427500204000ustar00rootroot00000000000000 libasm4-java-4.1/archive/asm-commons.bnd000066400000000000000000000045401207310427500201730ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### Implementation-Title: ASM commons classes Implementation-Version: ${product.artifact} Implementation-Vendor: France Telecom R&D Bundle-Name: ASM commons classes Bundle-Vendor: France Telecom R&D Bundle-Version: ${product.artifact} Bundle-DocURL: http://asm.objectweb.org Bundle-SymbolicName: org.objectweb.asm.commons Export-Package: \ org.objectweb.asm.commons;version=${product.artifact} Import-Package: \ org.objectweb.asm.*;version:="[${product.artifact},${product.artifact}]" Bundle-RequiredExecutionEnvironment: J2SE-1.3 -removeheaders:\ ANNV,\ DSTAMP,\ FRAMESV,\ RESIZEV,\ SIGV,\ TODAY,\ TSTAMP,\ WRITERV libasm4-java-4.1/archive/asm-commons.pom000066400000000000000000000040731207310427500202240ustar00rootroot00000000000000 4.0.0 asm-parent org.ow2.asm @product.artifact@ ASM Commons asm-commons jar asm-tree org.ow2.asm libasm4-java-4.1/archive/asm-commons.xml000066400000000000000000000056761207310427500202430ustar00rootroot00000000000000 libasm4-java-4.1/archive/asm-debug-all.bnd000066400000000000000000000046441207310427500203610ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### Implementation-Title: ASM all classes with debug info Implementation-Version: ${product.artifact} Implementation-Vendor: France Telecom R&D Bundle-Name: ASM all classes with debug info Bundle-Vendor: France Telecom R&D Bundle-Version: ${product.artifact} Bundle-DocURL: http://asm.objectweb.org Bundle-SymbolicName: org.objectweb.asm.all.debug Export-Package: \ !org.objectweb.asm.optimizer.*,\ org.objectweb.asm.*;version=${product.artifact} Import-Package: \ javax.xml.transform.*;resolution:="optional",\ org.xml.sax.*;resolution:="optional" Bundle-RequiredExecutionEnvironment: J2SE-1.5 -removeheaders:\ ANNV,\ DSTAMP,\ FRAMESV,\ RESIZEV,\ SIGV,\ TODAY,\ TSTAMP,\ WRITERV libasm4-java-4.1/archive/asm-debug-all.pom000066400000000000000000000037141207310427500204060ustar00rootroot00000000000000 4.0.0 org.ow2.asm asm-parent @product.artifact@ ASM Debug All org.ow2.asm asm-debug-all jar libasm4-java-4.1/archive/asm-debug-all.xml000066400000000000000000000063431207310427500204140ustar00rootroot00000000000000 It is highly recommended to use only the necessary ASM jars for your application instead of using the asm-all jar, unless you really need all ASM packages. libasm4-java-4.1/archive/asm-parent.pom000066400000000000000000000126041207310427500200410ustar00rootroot00000000000000 ow2 org.ow2 1.3 4.0.0 asm-parent org.ow2.asm @product.artifact@ pom ASM A very small and fast Java bytecode manipulation framework http://asm.objectweb.org/ ObjectWeb http://www.objectweb.org/ 2000 BSD http://asm.objectweb.org/license.html Eric Bruneton ebruneton ebruneton@free.fr Creator Java Developer Eugene Kuleshov eu eu@javatx.org Java Developer Remi Forax forax forax@univ-mlv.fr Java Developer scm:svn:svn://svn.forge.objectweb.org/svnroot/asm/trunk scm:svn:svn+ssh://${maven.username}@svn.forge.objectweb.org/svnroot/asm/trunk http://svn.forge.objectweb.org/cgi-bin/viewcvs.cgi/asm/trunk/ http://forge.objectweb.org/tracker/?group_id=23 asm ${project.groupId} ${project.version} asm-tree ${project.groupId} ${project.version} asm-analysis ${project.groupId} ${project.version} asm-commons ${project.groupId} ${project.version} asm-util ${project.groupId} ${project.version} asm-xml ${project.groupId} ${project.version} ASM Users List sympa@objectweb.org?subject=subscribe%20asm sympa@objectweb.org?subject=unsubscribe%20asm asm@objectweb.org http://www.objectweb.org/wws/arc/asm ASM Team List sympa@objectweb.org?subject=subscribe%20asm-team sympa@objectweb.org?subject=unsubscribe%20asm-team asm-team@objectweb.org http://www.objectweb.org/wws/arc/asm-team libasm4-java-4.1/archive/asm-parent.xml000066400000000000000000000047201207310427500200460ustar00rootroot00000000000000 libasm4-java-4.1/archive/asm-tree.bnd000066400000000000000000000045401207310427500174570ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### Implementation-Title: ASM Tree class visitor Implementation-Version: ${product.artifact} Implementation-Vendor: France Telecom R&D Bundle-Name: ASM Tree class visitor Bundle-Vendor: France Telecom R&D Bundle-Version: ${product.artifact} Bundle-DocURL: http://asm.objectweb.org Bundle-SymbolicName: org.objectweb.asm.tree Export-Package: \ org.objectweb.asm.tree;version=${product.artifact} Import-Package: \ org.objectweb.asm.*;version:="[${product.artifact},${product.artifact}]" Bundle-RequiredExecutionEnvironment: J2SE-1.3 -removeheaders:\ ANNV,\ DSTAMP,\ FRAMESV,\ RESIZEV,\ SIGV,\ TODAY,\ TSTAMP,\ WRITERV libasm4-java-4.1/archive/asm-tree.pom000066400000000000000000000040601207310427500175040ustar00rootroot00000000000000 4.0.0 asm-parent org.ow2.asm @product.artifact@ ASM Tree asm-tree jar asm org.ow2.asm libasm4-java-4.1/archive/asm-tree.xml000066400000000000000000000056651207310427500175250ustar00rootroot00000000000000 libasm4-java-4.1/archive/asm-util.bnd000066400000000000000000000045161207310427500175000ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### Implementation-Title: ASM Utilities Implementation-Version: ${product.artifact} Implementation-Vendor: France Telecom R&D Bundle-Name: ASM Utilities Bundle-Vendor: France Telecom R&D Bundle-Version: ${product.artifact} Bundle-DocURL: http://asm.objectweb.org Bundle-SymbolicName: org.objectweb.asm.util Export-Package: \ org.objectweb.asm.util;version=${product.artifact} Import-Package: \ org.objectweb.asm.*;version:="[${product.artifact},${product.artifact}]" Bundle-RequiredExecutionEnvironment: J2SE-1.3 -removeheaders:\ ANNV,\ DSTAMP,\ FRAMESV,\ RESIZEV,\ SIGV,\ TODAY,\ TSTAMP,\ WRITERV libasm4-java-4.1/archive/asm-util.pom000066400000000000000000000040651207310427500175270ustar00rootroot00000000000000 4.0.0 asm-parent org.ow2.asm @product.artifact@ ASM Util asm-util jar asm-tree org.ow2.asm libasm4-java-4.1/archive/asm-util.xml000066400000000000000000000056651207310427500175430ustar00rootroot00000000000000 libasm4-java-4.1/archive/asm-xml.bnd000066400000000000000000000047611207310427500173250ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### Implementation-Title: ASM XML classes Implementation-Version: ${product.artifact} Implementation-Vendor: Eugene Kuleshov Class-Path: asm-${product.artifact}.jar asm-util-${product.artifact}.jar asm-attrs-${product.artifact}.jar Main-Class: org.objectweb.asm.xml.Processor Bundle-Name: ASM xml classes Bundle-Vendor: France Telecom R&D Bundle-Version: ${product.artifact} Bundle-DocURL: http://asm.objectweb.org Bundle-SymbolicName: org.objectweb.asm.xml Export-Package: \ org.objectweb.asm.xml;version=${product.artifact} Import-Package: \ javax.xml.transform.*;resolution:="optional",\ org.xml.sax.*;resolution:="optional" Bundle-RequiredExecutionEnvironment: J2SE-1.3 -removeheaders:\ ANNV,\ DSTAMP,\ FRAMESV,\ RESIZEV,\ SIGV,\ TODAY,\ TSTAMP,\ WRITERV libasm4-java-4.1/archive/asm-xml.pom000066400000000000000000000040631207310427500173500ustar00rootroot00000000000000 4.0.0 asm-parent org.ow2.asm @product.artifact@ ASM XML asm-xml jar asm-util org.ow2.asm libasm4-java-4.1/archive/asm-xml.xml000066400000000000000000000056621207310427500173630ustar00rootroot00000000000000 libasm4-java-4.1/archive/asm.bnd000066400000000000000000000044171207310427500165250ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### Implementation-Title: ASM Implementation-Version: ${product.artifact} Implementation-Vendor: France Telecom R&D Bundle-Name: ASM Bundle-Vendor: France Telecom R&D Bundle-Version: ${product.artifact} Bundle-DocURL: http://asm.objectweb.org Bundle-SymbolicName: org.objectweb.asm Export-Package: \ org.objectweb.asm;version=${product.artifact}, \ org.objectweb.asm.signature;version=${product.artifact} Bundle-RequiredExecutionEnvironment: J2SE-1.3 -removeheaders:\ ANNV,\ DSTAMP,\ FRAMESV,\ RESIZEV,\ SIGV,\ TODAY,\ TSTAMP,\ WRITERV libasm4-java-4.1/archive/asm.pom000066400000000000000000000036341207310427500165550ustar00rootroot00000000000000 4.0.0 asm-parent org.ow2.asm @product.artifact@ ASM Core asm jar libasm4-java-4.1/archive/asm.xml000066400000000000000000000056501207310427500165620ustar00rootroot00000000000000 libasm4-java-4.1/build.properties000066400000000000000000000102641207310427500170510ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### # Some information about the product product.name asm product.version 4.1 # product.snapshot yes plugin.version 3.3.0 ############################################################################### # BUILD ############################################################################### # Wich compiler do you want to use ? # jikes is faster than javac but keeps line numbers in compiled classes, even # with the -O option (javac removes line numbers and local variable names with # this option, resulting in smaller classes) build.compiler modern # Build class path (classes needed to build the project) # Class path for the ObjectWeb utility Ant tasks (version 1.3.2 or higher) # See http://forge.objectweb.org/projects/monolog # objectweb.ant.tasks.path ow_util_ant_tasks.jar ############################################################################### # TESTS (PERFORMANCE COMPARISONS WITH BCEL AND SERP) ############################################################################### # Class path for the BCEL library (version 5.2) # See http://jakarta.apache.org/bcel # bcel.path bcel.jar # Class path for the AspectJ library that contains the modified BCEL version # (version 1.5) See http://www.eclipse.org/aspectj # aspectj.path aspectjweaver.jar # Class path for the SERP library (version 1.14.2) # See http://serp.sourceforge.net # serp.path serp.jar # Class path for the Javassist library (version 3.6.GA) # See http://www.csg.is.titech.ac.jp/~chiba/javassist # javassist.path javassist.jar # Class path for the Janino compiler (version 2.5.11) # See http://www.janino.net/ # janino.path janino.jar # Class paths for Cobertura (version 1.9) # corbertura.path cobertura.jar # cobertura.runtime.path cobertura.jar # Class paths for Kawa (version 1.9.1) # kawa.runtime.path kawa.jar # Class paths for CSG Bytecode # csg-bytecode.runtime.path csg-bytecode.jar # Class paths for Cojen (version 2.0) # cojen.runtime.path cojen.jar # Class paths for JBET (version 3-R1) # jbet.runtime.path jbet.jar # Class paths for JClassLib # jclasslib.runtime.path jclasslib.jar # Class paths for Jiapi # jiapi.runtime.path jiapi.jar # Class paths for mozilla.classfile (version 1_7R1) # rhino.runtime.path rhino.jar ############################################################################### # DOCUMENTATION ############################################################################### # URLs of external Javadocs (JDK) jdk.url http://java.sun.com/j2se/1.4.2/docs/api libasm4-java-4.1/build.xml000066400000000000000000000727031207310427500154630ustar00rootroot00000000000000 libasm4-java-4.1/doc/000077500000000000000000000000001207310427500143765ustar00rootroot00000000000000libasm4-java-4.1/doc/README.txt000066400000000000000000000034631207310427500161020ustar00rootroot00000000000000******************************************************************************* * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************* This directory contains the documentation of the product. libasm4-java-4.1/examples/000077500000000000000000000000001207310427500154475ustar00rootroot00000000000000libasm4-java-4.1/examples/adapt/000077500000000000000000000000001207310427500165405ustar00rootroot00000000000000libasm4-java-4.1/examples/adapt/etc/000077500000000000000000000000001207310427500173135ustar00rootroot00000000000000libasm4-java-4.1/examples/adapt/etc/execute.properties000066400000000000000000000034141207310427500230750ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### run.classname Adapt run.parameters ArraySet libasm4-java-4.1/examples/adapt/src/000077500000000000000000000000001207310427500173275ustar00rootroot00000000000000libasm4-java-4.1/examples/adapt/src/Adapt.java000066400000000000000000000173641207310427500212360ustar00rootroot00000000000000/*** * ASM examples: examples showing how ASM can be used * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; /** * @author Eric Bruneton */ public class Adapt extends ClassLoader { @Override protected synchronized Class loadClass(final String name, final boolean resolve) throws ClassNotFoundException { if (name.startsWith("java.")) { System.err.println("Adapt: loading class '" + name + "' without on the fly adaptation"); return super.loadClass(name, resolve); } else { System.err.println("Adapt: loading class '" + name + "' with on the fly adaptation"); } // gets an input stream to read the bytecode of the class String resource = name.replace('.', '/') + ".class"; InputStream is = getResourceAsStream(resource); byte[] b; // adapts the class on the fly try { ClassReader cr = new ClassReader(is); ClassWriter cw = new ClassWriter(0); ClassVisitor cv = new TraceFieldClassAdapter(cw); cr.accept(cv, 0); b = cw.toByteArray(); } catch (Exception e) { throw new ClassNotFoundException(name, e); } // optional: stores the adapted class on disk try { FileOutputStream fos = new FileOutputStream(resource + ".adapted"); fos.write(b); fos.close(); } catch (IOException e) { } // returns the adapted class return defineClass(name, b, 0, b.length); } public static void main(final String args[]) throws Exception { // loads the application class (in args[0]) with an Adapt class loader ClassLoader loader = new Adapt(); Class c = loader.loadClass(args[0]); // calls the 'main' static method of this class with the // application arguments (in args[1] ... args[n]) as parameter Method m = c.getMethod("main", new Class[] { String[].class }); String[] applicationArgs = new String[args.length - 1]; System.arraycopy(args, 1, applicationArgs, 0, applicationArgs.length); m.invoke(null, new Object[] { applicationArgs }); } } class TraceFieldClassAdapter extends ClassVisitor implements Opcodes { private String owner; public TraceFieldClassAdapter(final ClassVisitor cv) { super(Opcodes.ASM4, cv); } @Override public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) { owner = name; super.visit(version, access, name, signature, superName, interfaces); } @Override public FieldVisitor visitField(final int access, final String name, final String desc, final String signature, final Object value) { FieldVisitor fv = super .visitField(access, name, desc, signature, value); if ((access & ACC_STATIC) == 0) { Type t = Type.getType(desc); int size = t.getSize(); // generates getter method String gDesc = "()" + desc; MethodVisitor gv = cv.visitMethod(ACC_PRIVATE, "_get" + name, gDesc, null, null); gv.visitFieldInsn(GETSTATIC, "java/lang/System", "err", "Ljava/io/PrintStream;"); gv.visitLdcInsn("_get" + name + " called"); gv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); gv.visitVarInsn(ALOAD, 0); gv.visitFieldInsn(GETFIELD, owner, name, desc); gv.visitInsn(t.getOpcode(IRETURN)); gv.visitMaxs(1 + size, 1); gv.visitEnd(); // generates setter method String sDesc = "(" + desc + ")V"; MethodVisitor sv = cv.visitMethod(ACC_PRIVATE, "_set" + name, sDesc, null, null); sv.visitFieldInsn(GETSTATIC, "java/lang/System", "err", "Ljava/io/PrintStream;"); sv.visitLdcInsn("_set" + name + " called"); sv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); sv.visitVarInsn(ALOAD, 0); sv.visitVarInsn(t.getOpcode(ILOAD), 1); sv.visitFieldInsn(PUTFIELD, owner, name, desc); sv.visitInsn(RETURN); sv.visitMaxs(1 + size, 1 + size); sv.visitEnd(); } return fv; } @Override public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); return mv == null ? null : new TraceFieldCodeAdapter(mv, owner); } } class TraceFieldCodeAdapter extends MethodVisitor implements Opcodes { private String owner; public TraceFieldCodeAdapter(final MethodVisitor mv, final String owner) { super(Opcodes.ASM4, mv); this.owner = owner; } @Override public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) { if (owner.equals(this.owner)) { if (opcode == GETFIELD) { // replaces GETFIELD f by INVOKESPECIAL _getf String gDesc = "()" + desc; visitMethodInsn(INVOKESPECIAL, owner, "_get" + name, gDesc); return; } else if (opcode == PUTFIELD) { // replaces PUTFIELD f by INVOKESPECIAL _setf String sDesc = "(" + desc + ")V"; visitMethodInsn(INVOKESPECIAL, owner, "_set" + name, sDesc); return; } } super.visitFieldInsn(opcode, owner, name, desc); } } libasm4-java-4.1/examples/adapt/src/ArraySet.java000066400000000000000000000062521207310427500217310ustar00rootroot00000000000000/*** * ASM examples: examples showing how ASM can be used * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** * @author Eric Bruneton */ public class ArraySet { private int[] values = new int[3]; private int size; public boolean contains(final int v) { for (int i = 0; i < size; ++i) { if (values[i] == v) { return true; } } return false; } public void add(final int v) { if (!contains(v)) { if (size == values.length) { System.err.println("[enlarge]"); int[] newValues = new int[values.length + 3]; System.arraycopy(values, 0, newValues, 0, size); values = newValues; } values[size++] = v; } } public void remove(final int v) { int i = 0; int j = 0; while (i < size) { int u = values[i]; if (u != v) { values[j++] = u; } ++i; } size = j; } // test method public static void main(final String[] args) { ArraySet s = new ArraySet(); System.err.println("add 1"); s.add(1); System.err.println("add 1"); s.add(1); System.err.println("add 2"); s.add(2); System.err.println("add 4"); s.add(4); System.err.println("add 8"); s.add(8); System.err.println("contains 3 = " + s.contains(3)); System.err.println("contains 1 = " + s.contains(1)); System.err.println("remove 1"); s.remove(1); System.err.println("contains 1 = " + s.contains(1)); } } libasm4-java-4.1/examples/analysis/000077500000000000000000000000001207310427500172725ustar00rootroot00000000000000libasm4-java-4.1/examples/analysis/etc/000077500000000000000000000000001207310427500200455ustar00rootroot00000000000000libasm4-java-4.1/examples/analysis/etc/execute.properties000066400000000000000000000034061207310427500236300ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### run.classname Analysis run.parameters libasm4-java-4.1/examples/analysis/src/000077500000000000000000000000001207310427500200615ustar00rootroot00000000000000libasm4-java-4.1/examples/analysis/src/Analysis.java000066400000000000000000000170151207310427500225130ustar00rootroot00000000000000/*** * ASM examples: examples showing how ASM can be used * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.objectweb.asm.ClassReader; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.IincInsnNode; import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.VarInsnNode; import org.objectweb.asm.tree.analysis.Analyzer; import org.objectweb.asm.tree.analysis.BasicValue; import org.objectweb.asm.tree.analysis.BasicVerifier; import org.objectweb.asm.tree.analysis.Frame; import org.objectweb.asm.tree.analysis.SourceInterpreter; import org.objectweb.asm.tree.analysis.SourceValue; import org.objectweb.asm.util.TraceMethodVisitor; import org.objectweb.asm.util.Textifier; /** * @author Eric Bruneton */ public class Analysis implements Opcodes { public static void main(final String[] args) throws Exception { ClassReader cr = new ClassReader("Analysis"); ClassNode cn = new ClassNode(); cr.accept(cn, ClassReader.SKIP_DEBUG); List methods = cn.methods; for (int i = 0; i < methods.size(); ++i) { MethodNode method = methods.get(i); if (method.instructions.size() > 0) { if (!analyze(cn, method)) { Analyzer a = new Analyzer( new BasicVerifier()); try { a.analyze(cn.name, method); } catch (Exception ignored) { } final Frame[] frames = a.getFrames(); Textifier t = new Textifier() { @Override public void visitMaxs(final int maxStack, final int maxLocals) { for (int i = 0; i < text.size(); ++i) { StringBuffer s = new StringBuffer( frames[i] == null ? "null" : frames[i].toString()); while (s.length() < Math.max(20, maxStack + maxLocals + 1)) { s.append(' '); } System.err.print(Integer.toString(i + 1000) .substring(1) + " " + s + " : " + text.get(i)); } System.err.println(); } }; MethodVisitor mv = new TraceMethodVisitor(t); for (int j = 0; j < method.instructions.size(); ++j) { Object insn = method.instructions.get(j); ((AbstractInsnNode) insn).accept(mv); } mv.visitMaxs(0, 0); } } } } /* * Detects unused xSTORE instructions, i.e. xSTORE instructions without at * least one xLOAD corresponding instruction in their successor instructions * (in the control flow graph). */ public static boolean analyze(final ClassNode c, final MethodNode m) throws Exception { Analyzer a = new Analyzer( new SourceInterpreter()); Frame[] frames = a.analyze(c.name, m); // for each xLOAD instruction, we find the xSTORE instructions that can // produce the value loaded by this instruction, and we put them in // 'stores' Set stores = new HashSet(); for (int i = 0; i < m.instructions.size(); ++i) { AbstractInsnNode insn = m.instructions.get(i); int opcode = insn.getOpcode(); if ((opcode >= ILOAD && opcode <= ALOAD) || opcode == IINC) { int var = opcode == IINC ? ((IincInsnNode) insn).var : ((VarInsnNode) insn).var; Frame f = frames[i]; if (f != null) { Set s = f.getLocal(var).insns; Iterator j = s.iterator(); while (j.hasNext()) { insn = j.next(); if (insn instanceof VarInsnNode) { stores.add(insn); } } } } } // we then find all the xSTORE instructions that are not in 'stores' boolean ok = true; for (int i = 0; i < m.instructions.size(); ++i) { AbstractInsnNode insn = m.instructions.get(i); int opcode = insn.getOpcode(); if (opcode >= ISTORE && opcode <= ASTORE) { if (!stores.contains(insn)) { ok = false; System.err.println("method " + m.name + ", instruction " + i + ": useless store instruction"); } } } return ok; } /* * Test for the above method, with three useless xSTORE instructions. */ public int test(int i, int j) { i = i + 1; // ok, because i can be read after this point if (j == 0) { j = 1; // useless } else { try { j = j - 1; // ok, because j can be accessed in the catch int k = 0; if (i > 0) { k = i - 1; } return k; } catch (Exception e) { // useless ASTORE (e is never used) j = j + 1; // useless } } return 0; } } libasm4-java-4.1/examples/annotations/000077500000000000000000000000001207310427500200045ustar00rootroot00000000000000libasm4-java-4.1/examples/annotations/build.xml000066400000000000000000000066231207310427500216340ustar00rootroot00000000000000 libasm4-java-4.1/examples/annotations/etc/000077500000000000000000000000001207310427500205575ustar00rootroot00000000000000libasm4-java-4.1/examples/annotations/etc/execute.properties000066400000000000000000000034511207310427500243420ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### run.classname Annotations run.parameters libasm4-java-4.1/examples/annotations/src/000077500000000000000000000000001207310427500205735ustar00rootroot00000000000000libasm4-java-4.1/examples/annotations/src/Annotations.java000066400000000000000000000136231207310427500237400ustar00rootroot00000000000000/*** * ASM examples: examples showing how ASM can be used * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; public class Annotations { public static void foo(final @NotNull String arg) { System.out.println(arg); } public static void main(final String[] args) throws Exception { System.out .println("Calling foo(null) results in a NullPointerException:"); try { foo(null); } catch (Exception e) { e.printStackTrace(System.out); } final String n = Annotations.class.getName(); final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); ClassReader cr = new ClassReader(n); cr.accept(new ClassVisitor(Opcodes.ASM4, cw) { @Override public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { final Type[] args = Type.getArgumentTypes(desc); MethodVisitor v = cv.visitMethod(access, name, desc, signature, exceptions); return new MethodVisitor(Opcodes.ASM4, v) { private final List params = new ArrayList(); @Override public AnnotationVisitor visitParameterAnnotation( final int parameter, final String desc, final boolean visible) { AnnotationVisitor av; av = mv.visitParameterAnnotation(parameter, desc, visible); if (desc.equals("LNotNull;")) { params.add(new Integer(parameter)); } return av; } @Override public void visitCode() { int var = (access & Opcodes.ACC_STATIC) == 0 ? 1 : 0; for (int p = 0; p < params.size(); ++p) { int param = params.get(p).intValue(); for (int i = 0; i < param; ++i) { var += args[i].getSize(); } String c = "java/lang/IllegalArgumentException"; String d = "(Ljava/lang/String;)V"; Label end = new Label(); mv.visitVarInsn(Opcodes.ALOAD, var); mv.visitJumpInsn(Opcodes.IFNONNULL, end); mv.visitTypeInsn(Opcodes.NEW, c); mv.visitInsn(Opcodes.DUP); mv.visitLdcInsn("Argument " + param + " must not be null"); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, c, "", d); mv.visitInsn(Opcodes.ATHROW); mv.visitLabel(end); } } }; } }, 0); Class c = new ClassLoader() { @Override public Class loadClass(final String name) throws ClassNotFoundException { if (name.equals(n)) { byte[] b = cw.toByteArray(); return defineClass(name, b, 0, b.length); } return super.loadClass(name); } }.loadClass(n); System.out.println(); System.out.println("Calling foo(null) on the transformed class results" + " in an IllegalArgumentException:"); Method m = c.getMethod("foo", new Class[] { String.class }); try { m.invoke(null, new Object[] { null }); } catch (InvocationTargetException e) { e.getCause().printStackTrace(System.out); } } } libasm4-java-4.1/examples/annotations/src/NotNull.java000066400000000000000000000034431207310427500230350ustar00rootroot00000000000000/*** * ASM examples: examples showing how ASM can be used * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.CLASS) public @interface NotNull { String value() default ""; } libasm4-java-4.1/examples/attributes/000077500000000000000000000000001207310427500176355ustar00rootroot00000000000000libasm4-java-4.1/examples/attributes/etc/000077500000000000000000000000001207310427500204105ustar00rootroot00000000000000libasm4-java-4.1/examples/attributes/etc/execute.properties000066400000000000000000000034101207310427500241660ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### run.classname Attributes run.parameters libasm4-java-4.1/examples/attributes/src/000077500000000000000000000000001207310427500204245ustar00rootroot00000000000000libasm4-java-4.1/examples/attributes/src/Attributes.java000066400000000000000000000123461207310427500234230ustar00rootroot00000000000000/*** * ASM examples: examples showing how ASM can be used * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ import java.io.FileOutputStream; import java.io.PrintWriter; import java.util.Map; import org.objectweb.asm.Attribute; import org.objectweb.asm.ByteVector; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.util.Textifiable; import org.objectweb.asm.util.TraceClassVisitor; /** * @author Eric Bruneton */ public class Attributes extends ClassLoader { public static void main(final String args[]) throws Exception { // loads the original class and adapts it ClassReader cr = new ClassReader("CommentAttribute"); ClassWriter cw = new ClassWriter(0); ClassVisitor cv = new AddCommentClassAdapter(cw); cr.accept(cv, new Attribute[] { new CommentAttribute("") }, 0); byte[] b = cw.toByteArray(); // stores the adapted class on disk FileOutputStream fos = new FileOutputStream( "CommentAttribute.class.new"); try { fos.write(b); } finally { fos.close(); } // "disassembles" the adapted class cr = new ClassReader(b); cv = new TraceClassVisitor(new PrintWriter(System.out)); cr.accept(cv, new Attribute[] { new CommentAttribute("") }, 0); } } class AddCommentClassAdapter extends ClassVisitor implements Opcodes { public AddCommentClassAdapter(final ClassVisitor cv) { super(Opcodes.ASM4, cv); } @Override public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) { super.visit(version, access, name, signature, superName, interfaces); visitAttribute(new CommentAttribute("this is a class comment")); } @Override public FieldVisitor visitField(final int access, final String name, final String desc, final String signature, final Object value) { FieldVisitor fv = super .visitField(access, name, desc, signature, value); fv.visitAttribute(new CommentAttribute("this is a field comment")); return fv; } @Override public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); if (mv != null) { mv.visitAttribute(new CommentAttribute("this is a method comment")); } return mv; } } class CommentAttribute extends Attribute implements Textifiable { private String comment; public CommentAttribute(final String comment) { super("Comment"); this.comment = comment; } public String getComment() { return comment; } @Override public boolean isUnknown() { return false; } @Override protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, final int codeOff, final Label[] labels) { return new CommentAttribute(cr.readUTF8(off, buf)); } @Override protected ByteVector write(final ClassWriter cw, final byte[] code, final int len, final int maxStack, final int maxLocals) { return new ByteVector().putShort(cw.newUTF8(comment)); } public void textify(StringBuffer buf, Map labelNames) { buf.append(": " + comment + "\n"); } } libasm4-java-4.1/examples/common/000077500000000000000000000000001207310427500167375ustar00rootroot00000000000000libasm4-java-4.1/examples/common/README.txt000066400000000000000000000044701207310427500204420ustar00rootroot00000000000000******************************************************************************* * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************* This directory contains the examples of the product. It contains(*) the following items: - lib: jar files shared by all examples, - etc: configuration files shared by all examples, - README.txt: explains the organisation of the examples directory, - all other directories contain(*) the following items: - README.txt file: describes the example and its configuration, - lib: jar files needed by the example, - etc: configuration files needed by the example, - src: source code of the example. (*) some items may not be present, depending on the product or example.libasm4-java-4.1/examples/common/build.xml000066400000000000000000000071111207310427500205600ustar00rootroot00000000000000 libasm4-java-4.1/examples/common/etc/000077500000000000000000000000001207310427500175125ustar00rootroot00000000000000libasm4-java-4.1/examples/common/etc/build.properties000066400000000000000000000056411207310427500227350ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### # Wich compiler do you want use ? # build.compiler jikes # Runtime class path for the ASM library (version @product.version@) # See http://asm.objectweb.org asm.path ../../lib/asm-@product.version@.jar # Runtime class path for the ASM tree library (version @product.version@) # See http://asm.objectweb.org asm.tree.path ../../lib/asm-tree-@product.version@.jar # Runtime class path for the ASM analysis library (version @product.version@) # See http://asm.objectweb.org asm.analysis.path ../../lib/asm-analysis-@product.version@.jar # Runtime class path for the ASM attrs library (version @product.version@) # See http://asm.objectweb.org asm.attrs.path ../../lib/asm-attrs-@product.version@.jar # Runtime class path for the ASM util library (version @product.version@) # See http://asm.objectweb.org asm.util.path ../../lib/asm-util-@product.version@.jar # Runtime class path for the ASM commons library (version @product.version@) # See http://asm.objectweb.org asm.commons.path ../../lib/asm-commons-@product.version@.jar # Compile time class path for the whole ASM library (version @product.version@) # See http://asm.objectweb.org asm.debug.path ../../lib/all/asm-debug-all-@product.version@.jar libasm4-java-4.1/examples/compile-indy/000077500000000000000000000000001207310427500200405ustar00rootroot00000000000000libasm4-java-4.1/examples/compile-indy/etc/000077500000000000000000000000001207310427500206135ustar00rootroot00000000000000libasm4-java-4.1/examples/compile-indy/etc/execute.properties000066400000000000000000000034111207310427500243720ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### run.classname IndyCompile run.parameters libasm4-java-4.1/examples/compile-indy/src/000077500000000000000000000000001207310427500206275ustar00rootroot00000000000000libasm4-java-4.1/examples/compile-indy/src/IndyCompile.java000066400000000000000000000264401207310427500237140ustar00rootroot00000000000000/*** * ASM examples: examples showing how ASM can be used * This example is adapted from the example that you can find in examples/compile * and use invokedynamic to implement all operations. * * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ import static org.objectweb.asm.Opcodes.ACC_PUBLIC; import static org.objectweb.asm.Opcodes.ACC_STATIC; import static org.objectweb.asm.Opcodes.ALOAD; import static org.objectweb.asm.Opcodes.ARETURN; import static org.objectweb.asm.Opcodes.DUP; import static org.objectweb.asm.Opcodes.H_INVOKESTATIC; import static org.objectweb.asm.Opcodes.IFEQ; import static org.objectweb.asm.Opcodes.IFNE; import static org.objectweb.asm.Opcodes.POP; import static org.objectweb.asm.Opcodes.V1_7; import java.io.FileOutputStream; import java.lang.reflect.Method; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Handle; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; /** * @author Remi Forax * @author Eric Bruneton */ public class IndyCompile extends ClassLoader { public static void main(final String[] args) throws Throwable { // creates the expression tree corresponding to // exp(i) = i > 3 && 6 > i Exp exp = new And(new GT(new Var(0), new Cst(3)), new GT(new Cst(6), new Var(0))); // compiles this expression into a generic static method in a class IndyCompile main = new IndyCompile(); byte[] b = exp.compile("Example"); FileOutputStream fos = new FileOutputStream("Example.class"); fos.write(b); fos.close(); Class expClass = main.defineClass("Example", b, 0, b.length); Method expMethod = expClass.getDeclaredMethods()[0]; // ... and use it to evaluate exp(0) to exp(9) for (int i = 0; i < 10; ++i) { boolean val = (Boolean) expMethod.invoke(null, i); System.out.println(i + " > 3 && " + i + " < 6 = " + val); } // ... more fun, test with strings !!! for (int i = 0; i < 10; ++i) { boolean val = (Boolean) expMethod.invoke(null, Integer.toString(i)); System.out.println("\"" + i + "\" > 3 && 6 > \"" + i + "\" = " + val); } } /** * An abstract expression. */ static abstract class Exp { static final Handle CST = getHandle("cst", "Ljava/lang/Object;"); static final Handle UNARY = getHandle("unary", ""); static final Handle BINARY = getHandle("binary", ""); /** * Returns the maximum variable index used in this expression. * * @return the maximum variable index used in this expression, or -1 if * no variable is used. */ int getMaxVarIndex() { return -1; } /* * Returns the byte code of a class corresponding to this expression. */ byte[] compile(final String name) { // class header ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); cw.visit(V1_7, ACC_PUBLIC, name, null, "java/lang/Object", null); // eval method type StringBuilder desc = new StringBuilder("("); for (int i = 0; i <= getMaxVarIndex(); ++i) { desc.append("Ljava/lang/Object;"); } desc.append(")Ljava/lang/Object;"); // eval method MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "eval", desc.toString(), null, null); compile(mv); mv.visitInsn(ARETURN); // max stack and max locals automatically computed mv.visitMaxs(0, 0); mv.visitEnd(); return cw.toByteArray(); } /* * Compile this expression. This method must append to the given code * writer the byte code that evaluates and pushes on the stack the value * of this expression. */ abstract void compile(MethodVisitor mv); private static Handle getHandle(final String name, final String optArgs) { return new Handle( H_INVOKESTATIC, "RT", name, "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;" + optArgs + ")Ljava/lang/invoke/CallSite;"); } } /** * A constant expression. */ static class Cst extends Exp { private final Object value; Cst(final Object value) { this.value = value; } @Override void compile(final MethodVisitor mv) { if (value instanceof String) { mv.visitLdcInsn(value); return; } // instead of pushing the constant and then box it, we use // invokedynamic with the constant as bootstrap argument. The // boxing will be performed by the VM when calling the bootstrap // method mv.visitInvokeDynamicInsn("cst", "()Ljava/lang/Object;", CST, value); } } /** * A variable reference expression. */ static class Var extends Exp { final int index; Var(final int index) { this.index = index; } @Override int getMaxVarIndex() { return index; } @Override void compile(final MethodVisitor mv) { // pushes the 'index' local variable onto the stack mv.visitVarInsn(ALOAD, index); } } /** * An abstract binary expression. */ static abstract class BinaryExp extends Exp { final Exp e1; final Exp e2; @Override int getMaxVarIndex() { return Math.max(e1.getMaxVarIndex(), e2.getMaxVarIndex()); } BinaryExp(final Exp e1, final Exp e2) { this.e1 = e1; this.e2 = e2; } } /** * An addition expression. */ static class Add extends BinaryExp { Add(final Exp e1, final Exp e2) { super(e1, e2); } @Override void compile(final MethodVisitor mv) { // compiles e1, e2, and adds an instruction to add the two values e1.compile(mv); e2.compile(mv); mv.visitInvokeDynamicInsn("add", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", BINARY); } } /** * A multiplication expression. */ static class Mul extends BinaryExp { Mul(final Exp e1, final Exp e2) { super(e1, e2); } @Override void compile(final MethodVisitor mv) { // compiles e1, e2, and adds an instruction to multiply the two // values e1.compile(mv); e2.compile(mv); mv.visitInvokeDynamicInsn("mul", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", BINARY); } } /** * A "greater than" expression. */ static class GT extends BinaryExp { GT(final Exp e1, final Exp e2) { super(e1, e2); } @Override void compile(final MethodVisitor mv) { // compiles e1, e2, and adds the instructions to compare the two // values e1.compile(mv); e2.compile(mv); mv.visitInvokeDynamicInsn("gt", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", BINARY); } } /** * A logical "and" expression. */ static class And extends BinaryExp { And(final Exp e1, final Exp e2) { super(e1, e2); } @Override void compile(final MethodVisitor mv) { // compiles e1 e1.compile(mv); // tests if e1 is false mv.visitInsn(DUP); // convert to a boolean mv.visitInvokeDynamicInsn("asBoolean", "(Ljava/lang/Object;)Z", UNARY); Label end = new Label(); mv.visitJumpInsn(IFEQ, end); // case where e1 is true : e1 && e2 is equal to e2 mv.visitInsn(POP); e2.compile(mv); // if e1 is false, e1 && e2 is equal to e1: // we jump directly to this label, without evaluating e2 mv.visitLabel(end); } } /** * A logical "or" expression. */ static class Or extends BinaryExp { Or(final Exp e1, final Exp e2) { super(e1, e2); } @Override void compile(final MethodVisitor mv) { // compiles e1 e1.compile(mv); // tests if e1 is true mv.visitInsn(DUP); // convert to a boolean mv.visitInvokeDynamicInsn("asBoolean", "(Ljava/lang/Object;)Z", UNARY); Label end = new Label(); mv.visitJumpInsn(IFNE, end); // case where e1 is false : e1 || e2 is equal to e2 mv.visitInsn(POP); e2.compile(mv); // if e1 is true, e1 || e2 is equal to e1: // we jump directly to this label, without evaluating e2 mv.visitLabel(end); } } /** * A logical "not" expression. */ static class Not extends Exp { private final Exp e; Not(final Exp e) { this.e = e; } @Override int getMaxVarIndex() { return e.getMaxVarIndex(); } @Override void compile(final MethodVisitor mv) { // compiles e, and applies 'not' e.compile(mv); mv.visitInvokeDynamicInsn("not", "(Ljava/lang/Object;)Ljava/lang/Object;", UNARY); } } } libasm4-java-4.1/examples/compile-indy/src/RT.java000066400000000000000000000321641207310427500220250ustar00rootroot00000000000000/*** * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ import java.lang.invoke.CallSite; import java.lang.invoke.ConstantCallSite; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodType; import java.lang.invoke.MutableCallSite; import java.util.HashMap; /** * There are 3 bootstrap methods: - one for the constant that are initialized * once the first time the bootstrap method is called and after always reuse the * same constant. It's almost equivalent to an LDC but here the constant are * stored in boxed form e.g a java.lang.Integer containing 0 instead of an int * containing 0. * * - one for the unary operation 'not' and 'asBoolean', here the semantics is * hard coded, all primitive value are transformed as object by applying this * operation: (v == 0)? false: true * * - one for the binary operation 'add', 'mul' and 'gt', here the semantics can * be changed by adding more static methods in {@link BinaryOps}. This bootstrap * method is a little more complex because it creates an inlining cache to avoid * to recompute the binary method to call if the type of the two arguments * doesn't change. Also, if the expression is used a lot and trigger the JIT, it * will be able to inline the code of the operation directly at callsite. * * @author Remi Forax */ public class RT { /** * bootstrap method for constant */ public static CallSite cst(Lookup lookup, String name, MethodType type, Object constant) { return new ConstantCallSite(MethodHandles.constant(Object.class, constant)); } /** * bootstrap method for unary operation 'asBoolean' and 'not' */ public static CallSite unary(Lookup lookup, String name, MethodType type) { MethodHandle target; if (name.equals("asBoolean")) { target = MethodHandles.explicitCastArguments( MethodHandles.identity(Object.class), MethodType.methodType(boolean.class, Object.class)); } else { // "not" target = MethodHandles.explicitCastArguments(NOT, MethodType.methodType(Object.class, Object.class)); } return new ConstantCallSite(target); } /** * bootstrap method for binary operation 'add', 'mul' and 'gt' * * This bootstrap method doesn't install the target method handle directly, * because we want to install an inlining cache and we can't create an * inlining cache without knowing the class of the arguments. So this method * first installs a method handle that will call * {@link BinaryOpCallSite#fallback(Object, Object)} and the fallback method * will be called with the arguments and thus can install the inlining * cache. Also, the fallback has to be bound to a specific callsite to be * able to change its target after the first call, this part is done in the * constructor of {@link BinaryOpCallSite}. */ public static CallSite binary(Lookup lookup, String name, MethodType type) { BinaryOpCallSite callSite = new BinaryOpCallSite(name, type); callSite.setTarget(callSite.fallback); return callSite; } /** * Garbage class containing the method used to apply 'not' on a boolean. See * {@link RT#unary(Lookup, String, MethodType)} */ public static class UnayOps { public static Object not(boolean b) { return !b; } } private static final MethodHandle NOT; static { try { NOT = MethodHandles.publicLookup().findStatic(UnayOps.class, "not", MethodType.methodType(Object.class, boolean.class)); } catch (ReflectiveOperationException e) { throw new LinkageError(e.getMessage(), e); } } /** * A specific callsite that will install an 'inlining cache'. Because we * don't know until runtime which method handle to call, the lookup * depending on the dynamic type of the argument will be done at runtime * when the method {@link #fallback(Object, Object)} is called. To avoid to * do this dynamic lookup at each call, the fallback install two guards in * front of dispatch call that will check if the arguments class change or * not. If the arguments class don't change, the previously computed method * handle will be called again. Otherwise, a new method handle will be * computed and two new guards will be installed. */ static class BinaryOpCallSite extends MutableCallSite { private final String opName; final MethodHandle fallback; public BinaryOpCallSite(String opName, MethodType type) { super(type); this.opName = opName; this.fallback = FALLBACK.bindTo(this); } Object fallback(Object v1, Object v2) throws Throwable { // when you debug with this message // don't forget that && and || are lazy !! // System.out.println("fallback called with "+opName+'('+v1.getClass()+','+v2.getClass()+')'); Class class1 = v1.getClass(); Class class2 = v2.getClass(); MethodHandle op = lookupBinaryOp(opName, class1, class2); // convert arguments MethodType type = type(); MethodType opType = op.type(); if (opType.parameterType(0) == String.class) { if (opType.parameterType(1) == String.class) { op = MethodHandles.filterArguments(op, 0, TO_STRING, TO_STRING); } else { op = MethodHandles.filterArguments(op, 0, TO_STRING); op = MethodHandles.explicitCastArguments(op, type); } } else { if (opType.parameterType(1) == String.class) { op = MethodHandles.filterArguments(op, 1, TO_STRING); } op = MethodHandles.explicitCastArguments(op, type); } // prepare guard MethodHandle guard = MethodHandles.guardWithTest(TEST1 .bindTo(class1), MethodHandles.guardWithTest( TEST2.bindTo(class2), op, fallback), fallback); // install the inlining cache setTarget(guard); return op.invokeWithArguments(v1, v2); } public static boolean test1(Class v1Class, Object v1, Object v2) { return v1.getClass() == v1Class; } public static boolean test2(Class v2Class, Object v1, Object v2) { return v2.getClass() == v2Class; } private static final MethodHandle TO_STRING; private static final MethodHandle TEST1; private static final MethodHandle TEST2; private static final MethodHandle FALLBACK; static { Lookup lookup = MethodHandles.lookup(); try { TO_STRING = lookup.findVirtual(Object.class, "toString", MethodType.methodType(String.class)); MethodType testType = MethodType.methodType(boolean.class, Class.class, Object.class, Object.class); TEST1 = lookup.findStatic(BinaryOpCallSite.class, "test1", testType); TEST2 = lookup.findStatic(BinaryOpCallSite.class, "test2", testType); FALLBACK = lookup.findVirtual(BinaryOpCallSite.class, "fallback", MethodType.genericMethodType(2)); } catch (ReflectiveOperationException e) { throw new LinkageError(e.getMessage(), e); } } } /** * Garbage class that contains the raw operations used for binary * operations. All methods must be static returns an Object and takes the * same type for the two parameter types. * * See {@link RT#lookupBinaryOp(String, Class, Class)} for more info. */ public static class BinaryOps { public static Object add(int v1, int v2) { return v1 + v2; } public static Object add(double v1, double v2) { return v1 + v2; } public static Object add(String v1, String v2) { return v1 + v2; } public static Object mul(int v1, int v2) { return v1 * v2; } public static Object mul(double v1, double v2) { return v1 * v2; } public static Object gt(int v1, int v2) { return v1 > v2; } public static Object gt(double v1, double v2) { return v1 > v2; } public static Object gt(String v1, String v2) { return v1.compareTo(v2) > 0; } } /** * Select a most specific method among the ones defined in * {@link RT.BinaryOps}. The algorithm first find the most specific subtype * between class1 and class2. The order of the types is defined in * {@link RT#RANK_MAP}: Boolean < Byte < Short < Character < Integer < Long * < Float < Double < String then the algorithm lookup in * {@link RT.BinaryOps} to find a method with the name opName taking as * argument the primitive corresponding to the most specific subtype. If no * such method exist, the algorithm retry but looking for a method with a * more specific type (using the same order). The result of the lookup is * cached in {@link RT#BINARY_CACHE} to avoid to avoid to do a lookup (a * reflective call) on the same method twice. */ static MethodHandle lookupBinaryOp(String opName, Class class1, Class class2) { int rank = Math.max(RANK_MAP.get(class1), RANK_MAP.get(class2)); String mangledName = opName + rank; MethodHandle mh = BINARY_CACHE.get(mangledName); if (mh != null) { return mh; } for (; rank < PRIMITIVE_ARRAY.length;) { Class primitive = PRIMITIVE_ARRAY[rank]; try { mh = MethodHandles.publicLookup().findStatic( BinaryOps.class, opName, MethodType.methodType(Object.class, primitive, primitive)); } catch (NoSuchMethodException e) { rank = rank + 1; continue; } catch (IllegalAccessException e) { throw new LinkageError(e.getMessage(), e); } BINARY_CACHE.put(mangledName, mh); return mh; } throw new LinkageError("unknown operation " + opName + " (" + class1.getName() + ',' + class2.getName() + ')'); } private static final HashMap, Integer> RANK_MAP; private static final Class[] PRIMITIVE_ARRAY; private static final HashMap BINARY_CACHE; static { Class[] primitives = new Class[] { boolean.class, byte.class, short.class, char.class, int.class, long.class, float.class, double.class, String.class }; Class[] wrappers = new Class[] { Boolean.class, Byte.class, Short.class, Character.class, Integer.class, Long.class, Float.class, Double.class, String.class }; HashMap, Integer> rankMap = new HashMap, Integer>(); for (int i = 0; i < wrappers.length; i++) { rankMap.put(wrappers[i], i); } RANK_MAP = rankMap; PRIMITIVE_ARRAY = primitives; BINARY_CACHE = new HashMap(); } } libasm4-java-4.1/examples/compile/000077500000000000000000000000001207310427500170775ustar00rootroot00000000000000libasm4-java-4.1/examples/compile/etc/000077500000000000000000000000001207310427500176525ustar00rootroot00000000000000libasm4-java-4.1/examples/compile/etc/execute.properties000066400000000000000000000034051207310427500234340ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### run.classname Compile run.parameters libasm4-java-4.1/examples/compile/src/000077500000000000000000000000001207310427500176665ustar00rootroot00000000000000libasm4-java-4.1/examples/compile/src/Compile.java000066400000000000000000000175671207310427500221410ustar00rootroot00000000000000/*** * ASM examples: examples showing how ASM can be used * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ import java.io.FileOutputStream; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; /** * @author Eric Bruneton */ public class Compile extends ClassLoader { public static void main(final String[] args) throws Exception { // creates the expression tree corresponding to // exp(i) = i > 3 && 6 > i Exp exp = new And(new GT(new Var(0), new Cst(3)), new GT(new Cst(6), new Var(0))); // compiles this expression into an Expression class Compile main = new Compile(); byte[] b = exp.compile("Example"); FileOutputStream fos = new FileOutputStream("Example.class"); fos.write(b); fos.close(); Class expClass = main.defineClass("Example", b, 0, b.length); // instantiates this compiled expression class... Expression iexp = (Expression) expClass.newInstance(); // ... and uses it to evaluate exp(0) to exp(9) for (int i = 0; i < 10; ++i) { boolean val = iexp.eval(i, 0) == 1; System.out.println(i + " > 3 && " + i + " < 6 = " + val); } } } /** * An abstract expression. * * @author Eric Bruneton */ abstract class Exp implements Opcodes { /* * Returns the byte code of an Expression class corresponding to this * expression. */ byte[] compile(final String name) { // class header ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); cw.visit(V1_1, ACC_PUBLIC, name, null, "java/lang/Object", new String[] { Expression.class.getName() }); // default public constructor MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V"); mv.visitInsn(RETURN); mv.visitMaxs(1, 1); mv.visitEnd(); // eval method mv = cw.visitMethod(ACC_PUBLIC, "eval", "(II)I", null, null); compile(mv); mv.visitInsn(IRETURN); // max stack and max locals automatically computed mv.visitMaxs(0, 0); mv.visitEnd(); return cw.toByteArray(); } /* * Compile this expression. This method must append to the given code writer * the byte code that evaluates and pushes on the stack the value of this * expression. */ abstract void compile(MethodVisitor mv); } /** * A constant expression. */ class Cst extends Exp { int value; Cst(final int value) { this.value = value; } @Override void compile(final MethodVisitor mv) { // pushes the constant's value onto the stack mv.visitLdcInsn(new Integer(value)); } } /** * A variable reference expression. */ class Var extends Exp { int index; Var(final int index) { this.index = index + 1; } @Override void compile(final MethodVisitor mv) { // pushes the 'index' local variable onto the stack mv.visitVarInsn(ILOAD, index); } } /** * An abstract binary expression. */ abstract class BinaryExp extends Exp { Exp e1; Exp e2; BinaryExp(final Exp e1, final Exp e2) { this.e1 = e1; this.e2 = e2; } } /** * An addition expression. */ class Add extends BinaryExp { Add(final Exp e1, final Exp e2) { super(e1, e2); } @Override void compile(final MethodVisitor mv) { // compiles e1, e2, and adds an instruction to add the two values e1.compile(mv); e2.compile(mv); mv.visitInsn(IADD); } } /** * A multiplication expression. */ class Mul extends BinaryExp { Mul(final Exp e1, final Exp e2) { super(e1, e2); } @Override void compile(final MethodVisitor mv) { // compiles e1, e2, and adds an instruction to multiply the two values e1.compile(mv); e2.compile(mv); mv.visitInsn(IMUL); } } /** * A "greater than" expression. */ class GT extends BinaryExp { GT(final Exp e1, final Exp e2) { super(e1, e2); } @Override void compile(final MethodVisitor mv) { // compiles e1, e2, and adds the instructions to compare the two values e1.compile(mv); e2.compile(mv); Label iftrue = new Label(); Label end = new Label(); mv.visitJumpInsn(IF_ICMPGT, iftrue); // case where e1 <= e2 : pushes false and jump to "end" mv.visitLdcInsn(new Integer(0)); mv.visitJumpInsn(GOTO, end); // case where e1 > e2 : pushes true mv.visitLabel(iftrue); mv.visitLdcInsn(new Integer(1)); mv.visitLabel(end); } } /** * A logical "and" expression. */ class And extends BinaryExp { And(final Exp e1, final Exp e2) { super(e1, e2); } @Override void compile(final MethodVisitor mv) { // compiles e1 e1.compile(mv); // tests if e1 is false mv.visitInsn(DUP); Label end = new Label(); mv.visitJumpInsn(IFEQ, end); // case where e1 is true : e1 && e2 is equal to e2 mv.visitInsn(POP); e2.compile(mv); // if e1 is false, e1 && e2 is equal to e1: // we jump directly to this label, without evaluating e2 mv.visitLabel(end); } } /** * A logical "or" expression. */ class Or extends BinaryExp { Or(final Exp e1, final Exp e2) { super(e1, e2); } @Override void compile(final MethodVisitor mv) { // compiles e1 e1.compile(mv); // tests if e1 is true mv.visitInsn(DUP); Label end = new Label(); mv.visitJumpInsn(IFNE, end); // case where e1 is false : e1 || e2 is equal to e2 mv.visitInsn(POP); e2.compile(mv); // if e1 is true, e1 || e2 is equal to e1: // we jump directly to this label, without evaluating e2 mv.visitLabel(end); } } /** * A logical "not" expression. */ class Not extends Exp { Exp e; Not(final Exp e) { this.e = e; } @Override void compile(final MethodVisitor mv) { // computes !e1 by evaluating 1 - e1 mv.visitLdcInsn(new Integer(1)); e.compile(mv); mv.visitInsn(ISUB); } } libasm4-java-4.1/examples/compile/src/Expression.java000066400000000000000000000040341207310427500226710ustar00rootroot00000000000000/*** * ASM examples: examples showing how ASM can be used * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** * An integer or boolean expression of at most two variables. * * @author Eric Bruneton */ public interface Expression { /** * Evaluates this expression. * * @param i * the value of the first variable. * @param j * the value of the second variable. * @return the value of this expression for the given variable values. */ int eval(int i, int j); } libasm4-java-4.1/examples/dependencies/000077500000000000000000000000001207310427500200755ustar00rootroot00000000000000libasm4-java-4.1/examples/dependencies/etc/000077500000000000000000000000001207310427500206505ustar00rootroot00000000000000libasm4-java-4.1/examples/dependencies/etc/execute.properties000066400000000000000000000034761207310427500244420ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### run.classname org.objectweb.asm.depend.DependencyTracker run.parameters ../../lib/asm-4.0.jar libasm4-java-4.1/examples/dependencies/src/000077500000000000000000000000001207310427500206645ustar00rootroot00000000000000libasm4-java-4.1/examples/dependencies/src/org/000077500000000000000000000000001207310427500214535ustar00rootroot00000000000000libasm4-java-4.1/examples/dependencies/src/org/objectweb/000077500000000000000000000000001207310427500234175ustar00rootroot00000000000000libasm4-java-4.1/examples/dependencies/src/org/objectweb/asm/000077500000000000000000000000001207310427500241775ustar00rootroot00000000000000libasm4-java-4.1/examples/dependencies/src/org/objectweb/asm/depend/000077500000000000000000000000001207310427500254365ustar00rootroot00000000000000libasm4-java-4.1/examples/dependencies/src/org/objectweb/asm/depend/DependencyTracker.java000066400000000000000000000166241207310427500317040ustar00rootroot00000000000000/*** * ASM examples: examples showing how ASM can be used * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.objectweb.asm.depend; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.Map; import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import javax.imageio.ImageIO; import org.objectweb.asm.ClassReader; /** * DependencyTracker * * @author Eugene Kuleshov * * @see "http://www.onjava.com/pub/a/onjava/2005/08/17/asm3.html" */ public class DependencyTracker { private static final int CELL_PAD = 1; private static final int GRID_SIZE = 10; private static final int CELLS_SIZE = 8; private static final int LABEL_WIDTH = 200; private static final String LABEL_FONT = "Tahoma-9"; public static void main(final String[] args) throws IOException { DependencyVisitor v = new DependencyVisitor(); ZipFile f = new ZipFile(args[0]); long l1 = System.currentTimeMillis(); Enumeration en = f.entries(); while (en.hasMoreElements()) { ZipEntry e = en.nextElement(); String name = e.getName(); if (name.endsWith(".class")) { new ClassReader(f.getInputStream(e)).accept(v, 0); } } long l2 = System.currentTimeMillis(); Map> globals = v.getGlobals(); Set jarPackages = globals.keySet(); Set classPackages = v.getPackages(); int size = classPackages.size(); System.err.println("time: " + (l2 - l1) / 1000f + " " + size); String[] jarNames = jarPackages.toArray(new String[jarPackages.size()]); String[] classNames = classPackages.toArray(new String[classPackages .size()]); Arrays.sort(jarNames); Arrays.sort(classNames); buildDiagram(jarNames, classNames, globals); } public static void buildDiagram(final String[] jarNames, final String[] classNames, final Map> globals) throws IOException { // normalize int max = 0; for (int i = 0; i < classNames.length; i++) { Map map = globals.get(classNames[i]); if (map == null) { continue; } Integer maxCount = Collections.max(map.values()); if (maxCount > max) { max = maxCount; } } List colors = new ArrayList(); for (int i = LABEL_WIDTH; i >= 0; i--) { colors.add(new Color(i, i, 255)); } for (int i = 255; i >= 128; i--) { colors.add(new Color(0, 0, i)); } int maxcolor = colors.size() - 1; int heigh = CELL_PAD + (CELLS_SIZE + CELL_PAD) * classNames.length; int width = CELL_PAD + (CELLS_SIZE + CELL_PAD) * jarNames.length; BufferedImage img = new BufferedImage(width + LABEL_WIDTH, heigh + LABEL_WIDTH, BufferedImage.TYPE_INT_RGB); Graphics2D g = img.createGraphics(); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setColor(Color.WHITE); g.fillRect(0, 0, width + LABEL_WIDTH, heigh + LABEL_WIDTH); // draw lines g.setColor(Color.LIGHT_GRAY); for (int y = GRID_SIZE; y < classNames.length; y += GRID_SIZE) { g.drawLine(0, y * (CELLS_SIZE + CELL_PAD), width, y * (CELLS_SIZE + CELL_PAD)); } for (int x = GRID_SIZE; x < jarNames.length; x += GRID_SIZE) { g.drawLine(x * (CELLS_SIZE + CELL_PAD), 0, x * (CELLS_SIZE + CELL_PAD), heigh); } // draw diagram for (int y = 0; y < classNames.length; y++) { // System.err.println( y+" : "+classNames[ y]); for (int x = 0; x < jarNames.length; x++) { Map map = globals.get(jarNames[x]); Integer count = map == null ? null : map.get(classNames[y]); if (count != null) { int b = (int) ((float) count * maxcolor / max); g.setColor(colors.get(b)); g.fillRect(CELL_PAD + x * (CELLS_SIZE + CELL_PAD), CELL_PAD + y * (CELLS_SIZE + CELL_PAD), CELLS_SIZE, CELLS_SIZE); } } } // draw labels Font f = Font.decode(LABEL_FONT); g.setFont(f); // g.setColor( new Color( 70, 70, 255)); g.setColor(Color.GRAY); for (int y = 0; y < classNames.length; y++) { AffineTransform trans = g.getTransform(); g.transform(AffineTransform.getTranslateInstance(CELL_PAD * 2 + width, CELLS_SIZE + y * (CELLS_SIZE + CELL_PAD))); g.transform(AffineTransform.getRotateInstance(Math.PI / 12)); g.drawString(classNames[y], 0, 0); g.setTransform(trans); } for (int x = 0; x < jarNames.length; x++) { AffineTransform trans = g.getTransform(); g.transform(AffineTransform.getTranslateInstance(CELL_PAD * 2 + x * (CELLS_SIZE + CELL_PAD), heigh + CELL_PAD * 2)); g.transform(AffineTransform.getRotateInstance(Math.PI / 2.5)); g.drawString(jarNames[x], 0, 0); g.setTransform(trans); } FileOutputStream fos = new FileOutputStream("test.png"); ImageIO.write(img, "png", fos); fos.flush(); fos.close(); } } libasm4-java-4.1/examples/dependencies/src/org/objectweb/asm/depend/DependencyVisitor.java000066400000000000000000000247661207310427500317560ustar00rootroot00000000000000/*** * ASM examples: examples showing how ASM can be used * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.objectweb.asm.depend; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.Handle; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.signature.SignatureReader; import org.objectweb.asm.signature.SignatureVisitor; /** * DependencyVisitor * * @author Eugene Kuleshov */ public class DependencyVisitor extends ClassVisitor { Set packages = new HashSet(); Map> groups = new HashMap>(); Map current; public Map> getGlobals() { return groups; } public Set getPackages() { return packages; } public DependencyVisitor() { super(Opcodes.ASM4); } // ClassVisitor @Override public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) { String p = getGroupKey(name); current = groups.get(p); if (current == null) { current = new HashMap(); groups.put(p, current); } if (signature == null) { if (superName != null) { addInternalName(superName); } addInternalNames(interfaces); } else { addSignature(signature); } } @Override public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { addDesc(desc); return new AnnotationDependencyVisitor(); } @Override public FieldVisitor visitField(final int access, final String name, final String desc, final String signature, final Object value) { if (signature == null) { addDesc(desc); } else { addTypeSignature(signature); } if (value instanceof Type) { addType((Type) value); } return new FieldDependencyVisitor(); } @Override public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { if (signature == null) { addMethodDesc(desc); } else { addSignature(signature); } addInternalNames(exceptions); return new MethodDependencyVisitor(); } class AnnotationDependencyVisitor extends AnnotationVisitor { public AnnotationDependencyVisitor() { super(Opcodes.ASM4); } @Override public void visit(final String name, final Object value) { if (value instanceof Type) { addType((Type) value); } } @Override public void visitEnum(final String name, final String desc, final String value) { addDesc(desc); } @Override public AnnotationVisitor visitAnnotation(final String name, final String desc) { addDesc(desc); return this; } @Override public AnnotationVisitor visitArray(final String name) { return this; } } class FieldDependencyVisitor extends FieldVisitor { public FieldDependencyVisitor() { super(Opcodes.ASM4); } @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { addDesc(desc); return new AnnotationDependencyVisitor(); } } class MethodDependencyVisitor extends MethodVisitor { public MethodDependencyVisitor() { super(Opcodes.ASM4); } @Override public AnnotationVisitor visitAnnotationDefault() { return new AnnotationDependencyVisitor(); } @Override public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { addDesc(desc); return new AnnotationDependencyVisitor(); } @Override public AnnotationVisitor visitParameterAnnotation(final int parameter, final String desc, final boolean visible) { addDesc(desc); return new AnnotationDependencyVisitor(); } @Override public void visitTypeInsn(final int opcode, final String type) { addType(Type.getObjectType(type)); } @Override public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) { addInternalName(owner); addDesc(desc); } @Override public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) { addInternalName(owner); addMethodDesc(desc); } @Override public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { addMethodDesc(desc); addConstant(bsm); for (int i = 0; i < bsmArgs.length; i++) { addConstant(bsmArgs[i]); } } @Override public void visitLdcInsn(final Object cst) { addConstant(cst); } @Override public void visitMultiANewArrayInsn(final String desc, final int dims) { addDesc(desc); } @Override public void visitLocalVariable(final String name, final String desc, final String signature, final Label start, final Label end, final int index) { addTypeSignature(signature); } @Override public void visitTryCatchBlock(final Label start, final Label end, final Label handler, final String type) { if (type != null) { addInternalName(type); } } } class SignatureDependencyVisitor extends SignatureVisitor { String signatureClassName; public SignatureDependencyVisitor() { super(Opcodes.ASM4); } @Override public void visitClassType(final String name) { signatureClassName = name; addInternalName(name); } @Override public void visitInnerClassType(final String name) { signatureClassName = signatureClassName + "$" + name; addInternalName(signatureClassName); } } // --------------------------------------------- private String getGroupKey(String name) { int n = name.lastIndexOf('/'); if (n > -1) { name = name.substring(0, n); } packages.add(name); return name; } private void addName(final String name) { if (name == null) { return; } String p = getGroupKey(name); if (current.containsKey(p)) { current.put(p, current.get(p) + 1); } else { current.put(p, 1); } } void addInternalName(final String name) { addType(Type.getObjectType(name)); } private void addInternalNames(final String[] names) { for (int i = 0; names != null && i < names.length; i++) { addInternalName(names[i]); } } void addDesc(final String desc) { addType(Type.getType(desc)); } void addMethodDesc(final String desc) { addType(Type.getReturnType(desc)); Type[] types = Type.getArgumentTypes(desc); for (int i = 0; i < types.length; i++) { addType(types[i]); } } void addType(final Type t) { switch (t.getSort()) { case Type.ARRAY: addType(t.getElementType()); break; case Type.OBJECT: addName(t.getInternalName()); break; case Type.METHOD: addMethodDesc(t.getDescriptor()); break; } } private void addSignature(final String signature) { if (signature != null) { new SignatureReader(signature) .accept(new SignatureDependencyVisitor()); } } void addTypeSignature(final String signature) { if (signature != null) { new SignatureReader(signature) .acceptType(new SignatureDependencyVisitor()); } } void addConstant(final Object cst) { if (cst instanceof Type) { addType((Type) cst); } else if (cst instanceof Handle) { Handle h = (Handle) cst; addInternalName(h.getOwner()); addMethodDesc(h.getDesc()); } } } libasm4-java-4.1/examples/helloworld/000077500000000000000000000000001207310427500176225ustar00rootroot00000000000000libasm4-java-4.1/examples/helloworld/etc/000077500000000000000000000000001207310427500203755ustar00rootroot00000000000000libasm4-java-4.1/examples/helloworld/etc/execute.properties000066400000000000000000000034101207310427500241530ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### run.classname Helloworld run.parameters libasm4-java-4.1/examples/helloworld/src/000077500000000000000000000000001207310427500204115ustar00rootroot00000000000000libasm4-java-4.1/examples/helloworld/src/Helloworld.java000066400000000000000000000136041207310427500233730ustar00rootroot00000000000000/*** * ASM examples: examples showing how ASM can be used * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ import java.io.FileOutputStream; import java.io.PrintStream; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.commons.GeneratorAdapter; import org.objectweb.asm.commons.Method; /** * @author Eric Bruneton */ public class Helloworld extends ClassLoader implements Opcodes { public static void main(final String args[]) throws Exception { // Generates the bytecode corresponding to the following Java class: // // public class Example { // public static void main (String[] args) { // System.out.println("Hello world!"); // } // } // creates a ClassWriter for the Example public class, // which inherits from Object ClassWriter cw = new ClassWriter(0); cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null); // creates a MethodWriter for the (implicit) constructor MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); // pushes the 'this' variable mw.visitVarInsn(ALOAD, 0); // invokes the super class constructor mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V"); mw.visitInsn(RETURN); // this code uses a maximum of one stack element and one local variable mw.visitMaxs(1, 1); mw.visitEnd(); // creates a MethodWriter for the 'main' method mw = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null); // pushes the 'out' field (of type PrintStream) of the System class mw.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); // pushes the "Hello World!" String constant mw.visitLdcInsn("Hello world!"); // invokes the 'println' method (defined in the PrintStream class) mw.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); mw.visitInsn(RETURN); // this code uses a maximum of two stack elements and two local // variables mw.visitMaxs(2, 2); mw.visitEnd(); // gets the bytecode of the Example class, and loads it dynamically byte[] code = cw.toByteArray(); FileOutputStream fos = new FileOutputStream("Example.class"); fos.write(code); fos.close(); Helloworld loader = new Helloworld(); Class exampleClass = loader.defineClass("Example", code, 0, code.length); // uses the dynamically generated class to print 'Helloworld' exampleClass.getMethods()[0].invoke(null, new Object[] { null }); // ------------------------------------------------------------------------ // Same example with a GeneratorAdapter (more convenient but slower) // ------------------------------------------------------------------------ cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null); // creates a GeneratorAdapter for the (implicit) constructor Method m = Method.getMethod("void ()"); GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cw); mg.loadThis(); mg.invokeConstructor(Type.getType(Object.class), m); mg.returnValue(); mg.endMethod(); // creates a GeneratorAdapter for the 'main' method m = Method.getMethod("void main (String[])"); mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw); mg.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class)); mg.push("Hello world!"); mg.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod("void println (String)")); mg.returnValue(); mg.endMethod(); cw.visitEnd(); code = cw.toByteArray(); loader = new Helloworld(); exampleClass = loader.defineClass("Example", code, 0, code.length); // uses the dynamically generated class to print 'Helloworld' exampleClass.getMethods()[0].invoke(null, new Object[] { null }); } } libasm4-java-4.1/examples/jasmin/000077500000000000000000000000001207310427500167305ustar00rootroot00000000000000libasm4-java-4.1/examples/jasmin/etc/000077500000000000000000000000001207310427500175035ustar00rootroot00000000000000libasm4-java-4.1/examples/jasmin/etc/execute.properties000066400000000000000000000034461207310427500232720ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### run.classname JasminifierClassAdapter run.parameters java.lang.Object libasm4-java-4.1/examples/jasmin/src/000077500000000000000000000000001207310427500175175ustar00rootroot00000000000000libasm4-java-4.1/examples/jasmin/src/JasminifierClassAdapter.java000066400000000000000000001033241207310427500251140ustar00rootroot00000000000000/*** * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ import java.io.FileInputStream; import java.io.PrintWriter; import java.util.HashMap; import java.util.List; import java.util.Map; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.AnnotationNode; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.FieldNode; import org.objectweb.asm.tree.InnerClassNode; import org.objectweb.asm.tree.LabelNode; import org.objectweb.asm.tree.LocalVariableNode; import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.TryCatchBlockNode; import org.objectweb.asm.util.Printer; /** * A {@link ClassVisitor} that prints a disassembled view of the classes it * visits in Jasmin assembler format. This class visitor can be used alone (see * the {@link #main main} method) to disassemble a class. It can also be used in * the middle of class visitor chain to trace the class that is visited at a * given point in this chain. This may be uselful for debugging purposes. *

* The trace printed when visiting the Hello class is the following: *

*

* *
 * .bytecode 45.3
 * .class public Hello
 * .super java/lang/Object
 * 
 * .method public ()V
 * aload 0
 * invokespecial java/lang/Object/()V
 * return
 * .limit locals 1
 * .limit stack 1
 * .end method
 * 
 * .method public static main([Ljava/lang/String;)V
 * getstatic java/lang/System/out Ljava/io/PrintStream;
 * ldc "hello"
 * invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
 * return
 * .limit locals 2
 * .limit stack 2
 * .end method
 * 
* *
where Hello is defined by: *

*

* *
 * public class Hello {
 * 
 *     public static void main(String[] args) {
 *         System.out.println("hello");
 *     }
 * }
 * 
* *
* * @author Eric Bruneton */ public class JasminifierClassAdapter extends ClassVisitor { /** * The print writer to be used to print the class. */ protected PrintWriter pw; /** * The label names. This map associate String values to Label keys. */ protected final Map labelNames; /** * Prints a disassembled view of the given class in Jasmin assembler format * to the standard output. *

* Usage: JasminifierClassAdapter [-debug] <fully qualified class name or * class file name > * * @param args * the command line arguments. * * @throws Exception * if the class cannot be found, or if an IO exception occurs. */ public static void main(final String[] args) throws Exception { int i = 0; int flags = ClassReader.SKIP_DEBUG; boolean ok = true; if (args.length < 1 || args.length > 2) { ok = false; } if (ok && "-debug".equals(args[0])) { i = 1; flags = 0; if (args.length != 2) { ok = false; } } if (!ok) { System.err .println("Prints a disassembled view of the given class."); System.err.println("Usage: JasminifierClassAdapter [-debug] " + ""); return; } ClassReader cr; if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1 || args[i].indexOf('/') > -1) { cr = new ClassReader(new FileInputStream(args[i])); } else { cr = new ClassReader(args[i]); } cr.accept(new JasminifierClassAdapter( new PrintWriter(System.out, true), null), flags | ClassReader.EXPAND_FRAMES); } /** * Constructs a new {@link JasminifierClassAdapter}. * * @param pw * the print writer to be used to print the class. * @param cv * the {@link ClassVisitor} to which this visitor delegates * calls. May be null. */ public JasminifierClassAdapter(final PrintWriter pw, final ClassVisitor cv) { super(Opcodes.ASM4, new ClassNode() { @Override public void visitEnd() { if (cv != null) { accept(cv); } } }); this.pw = pw; labelNames = new HashMap(); } @Override public void visitEnd() { ClassNode cn = (ClassNode) cv; pw.print(".bytecode "); pw.print(cn.version & 0xFFFF); pw.print('.'); pw.println(cn.version >>> 16); println(".source ", cn.sourceFile); pw.print(".class"); pw.print(access(cn.access)); pw.print(' '); pw.println(cn.name); if (cn.superName == null) { // TODO Jasmin bug workaround println(".super ", "java/lang/Object"); } else { println(".super ", cn.superName); } for (int i = 0; i < cn.interfaces.size(); ++i) { println(".implements ", cn.interfaces.get(i)); } if (cn.signature != null) println(".signature ", '"' + cn.signature + '"'); if (cn.outerClass != null) { pw.print(".enclosing method "); pw.print(cn.outerClass); if (cn.outerMethod != null) { pw.print('/'); pw.print(cn.outerMethod); pw.println(cn.outerMethodDesc); } else { pw.println(); } } if ((cn.access & Opcodes.ACC_DEPRECATED) != 0) { pw.println(".deprecated"); } printAnnotations(cn.visibleAnnotations, 1); printAnnotations(cn.invisibleAnnotations, 2); println(".debug ", cn.sourceDebug == null ? null : '"' + cn.sourceDebug + '"'); for (int i = 0; i < cn.innerClasses.size(); ++i) { InnerClassNode in = cn.innerClasses.get(i); pw.print(".inner class"); pw.print(access(in.access)); if (in.innerName != null) { pw.print(' '); pw.print(in.innerName); } if (in.name != null) { pw.print(" inner "); pw.print(in.name); } if (in.outerName != null) { pw.print(" outer "); pw.print(in.outerName); } pw.println(); } for (int i = 0; i < cn.fields.size(); ++i) { FieldNode fn = cn.fields.get(i); boolean annotations = false; if (fn.visibleAnnotations != null && fn.visibleAnnotations.size() > 0) { annotations = true; } if (fn.invisibleAnnotations != null && fn.invisibleAnnotations.size() > 0) { annotations = true; } boolean deprecated = (fn.access & Opcodes.ACC_DEPRECATED) != 0; pw.print("\n.field"); pw.print(access(fn.access)); pw.print(" '"); pw.print(fn.name); pw.print("' "); pw.print(fn.desc); if (fn.signature != null && (!deprecated && !annotations)) { pw.print(" signature \""); pw.print(fn.signature); pw.print("\""); } if (fn.value instanceof String) { StringBuffer buf = new StringBuffer(); Printer.appendString(buf, (String) fn.value); pw.print(" = "); pw.print(buf.toString()); } else if (fn.value != null) { pw.print(" = "); print(fn.value); pw.println(); } pw.println(); if (fn.signature != null && (deprecated || annotations)) { pw.print(".signature \""); pw.print(fn.signature); pw.println("\""); } if (deprecated) { pw.println(".deprecated"); } printAnnotations(fn.visibleAnnotations, 1); printAnnotations(fn.invisibleAnnotations, 2); if (deprecated || annotations) { pw.println(".end field"); } } for (int i = 0; i < cn.methods.size(); ++i) { MethodNode mn = cn.methods.get(i); pw.print("\n.method"); pw.print(access(mn.access)); pw.print(' '); pw.print(mn.name); pw.println(mn.desc); if (mn.signature != null) { pw.print(".signature \""); pw.print(mn.signature); pw.println("\""); } if (mn.annotationDefault != null) { pw.println(".annotation default"); printAnnotationValue(mn.annotationDefault); pw.println(".end annotation"); } printAnnotations(mn.visibleAnnotations, 1); printAnnotations(mn.invisibleAnnotations, 2); if (mn.visibleParameterAnnotations != null) { for (int j = 0; j < mn.visibleParameterAnnotations.length; ++j) { printAnnotations(mn.visibleParameterAnnotations[j], 1); } } if (mn.invisibleParameterAnnotations != null) { for (int j = 0; j < mn.invisibleParameterAnnotations.length; ++j) { printAnnotations(mn.invisibleParameterAnnotations[j], 2); } } for (int j = 0; j < mn.exceptions.size(); ++j) { println(".throws ", mn.exceptions.get(j)); } if ((mn.access & Opcodes.ACC_DEPRECATED) != 0) { pw.println(".deprecated"); } if (mn.instructions.size() > 0) { labelNames.clear(); for (int j = 0; j < mn.tryCatchBlocks.size(); ++j) { TryCatchBlockNode tcb = mn.tryCatchBlocks.get(j); pw.print(".catch "); pw.print(tcb.type); pw.print(" from "); print(tcb.start); pw.print(" to "); print(tcb.end); pw.print(" using "); print(tcb.handler); pw.println(); } for (int j = 0; j < mn.instructions.size(); ++j) { AbstractInsnNode in = mn.instructions.get(j); in.accept(new MethodVisitor(Opcodes.ASM4) { @Override public void visitFrame(int type, int local, Object[] locals, int stack, Object[] stacks) { if (type != Opcodes.F_FULL && type != Opcodes.F_NEW) { throw new RuntimeException( "Compressed frames unsupported, use EXPAND_FRAMES option"); } pw.println(".stack"); for (int i = 0; i < local; ++i) { pw.print("locals "); printFrameType(locals[i]); pw.println(); } for (int i = 0; i < stack; ++i) { pw.print("stack "); printFrameType(stacks[i]); pw.println(); } pw.println(".end stack"); } @Override public void visitInsn(int opcode) { print(opcode); pw.println(); } @Override public void visitIntInsn(int opcode, int operand) { print(opcode); if (opcode == Opcodes.NEWARRAY) { switch (operand) { case Opcodes.T_BOOLEAN: pw.println(" boolean"); break; case Opcodes.T_CHAR: pw.println(" char"); break; case Opcodes.T_FLOAT: pw.println(" float"); break; case Opcodes.T_DOUBLE: pw.println(" double"); break; case Opcodes.T_BYTE: pw.println(" byte"); break; case Opcodes.T_SHORT: pw.println(" short"); break; case Opcodes.T_INT: pw.println(" int"); break; case Opcodes.T_LONG: default: pw.println(" long"); break; } } else { pw.print(' '); pw.println(operand); } } @Override public void visitVarInsn(int opcode, int var) { print(opcode); pw.print(' '); pw.println(var); } @Override public void visitTypeInsn(int opcode, String type) { print(opcode); pw.print(' '); pw.println(type); } @Override public void visitFieldInsn(int opcode, String owner, String name, String desc) { print(opcode); pw.print(' '); pw.print(owner); pw.print('/'); pw.print(name); pw.print(' '); pw.println(desc); } @Override public void visitMethodInsn(int opcode, String owner, String name, String desc) { print(opcode); pw.print(' '); pw.print(owner); pw.print('/'); pw.print(name); pw.print(desc); if (opcode == Opcodes.INVOKEINTERFACE) { pw.print(' '); pw.print((Type.getArgumentsAndReturnSizes(desc) >> 2) - 1); } pw.println(); } @Override public void visitJumpInsn(int opcode, Label label) { print(opcode); pw.print(' '); print(label); pw.println(); } @Override public void visitLabel(Label label) { print(label); pw.println(':'); } @Override public void visitLdcInsn(Object cst) { pw.print("ldc "); if (cst instanceof Type) { pw.print(((Type) cst).getInternalName()); } else { print(cst); } pw.println(); } @Override public void visitIincInsn(int var, int increment) { pw.print("iinc "); pw.print(var); pw.print(' '); pw.println(increment); } @Override public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) { pw.print("tableswitch "); pw.println(min); for (int i = 0; i < labels.length; ++i) { print(labels[i]); pw.println(); } pw.print("default : "); print(dflt); pw.println(); } @Override public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { if (keys.length == 0) { pw.print("goto "); // TODO Jasmin bug // workaround print(dflt); pw.println(); return; } pw.println("lookupswitch"); for (int i = 0; i < keys.length; ++i) { pw.print(keys[i]); pw.print(" : "); print(labels[i]); pw.println(); } pw.print("default : "); print(dflt); pw.println(); } @Override public void visitMultiANewArrayInsn(String desc, int dims) { pw.print("multianewarray "); pw.print(desc); pw.print(' '); pw.println(dims); } @Override public void visitLineNumber(int line, Label start) { pw.print(".line "); pw.println(line); } }); } for (int j = 0; j < mn.localVariables.size(); ++j) { LocalVariableNode lv = mn.localVariables.get(j); pw.print(".var "); pw.print(lv.index); pw.print(" is '"); pw.print(lv.name); pw.print("' "); pw.print(lv.desc); if (lv.signature != null) { pw.print(" signature \""); pw.print(lv.signature); pw.print("\""); } pw.print(" from "); print(lv.start); pw.print(" to "); print(lv.end); pw.println(); } println(".limit locals ", Integer.toString(mn.maxLocals)); println(".limit stack ", Integer.toString(mn.maxStack)); } pw.println(".end method"); } super.visitEnd(); } protected void println(final String directive, final String arg) { if (arg != null) { pw.print(directive); pw.println(arg); } } protected String access(final int access) { StringBuffer b = new StringBuffer(); if ((access & Opcodes.ACC_PUBLIC) != 0) { b.append(" public"); } if ((access & Opcodes.ACC_PRIVATE) != 0) { b.append(" private"); } if ((access & Opcodes.ACC_PROTECTED) != 0) { b.append(" protected"); } if ((access & Opcodes.ACC_STATIC) != 0) { b.append(" static"); } if ((access & Opcodes.ACC_FINAL) != 0) { b.append(" final"); } if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) { b.append(" synchronized"); } if ((access & Opcodes.ACC_VOLATILE) != 0) { b.append(" volatile"); } if ((access & Opcodes.ACC_TRANSIENT) != 0) { b.append(" transient"); } if ((access & Opcodes.ACC_NATIVE) != 0) { b.append(" native"); } if ((access & Opcodes.ACC_ABSTRACT) != 0) { b.append(" abstract"); } if ((access & Opcodes.ACC_STRICT) != 0) { b.append(" fpstrict"); } if ((access & Opcodes.ACC_SYNTHETIC) != 0) { b.append(" synthetic"); } if ((access & Opcodes.ACC_INTERFACE) != 0) { b.append(" interface"); } if ((access & Opcodes.ACC_ANNOTATION) != 0) { b.append(" annotation"); } if ((access & Opcodes.ACC_ENUM) != 0) { b.append(" enum"); } return b.toString(); } protected void print(final int opcode) { pw.print(Printer.OPCODES[opcode].toLowerCase()); } protected void print(final Object cst) { if (cst instanceof String) { StringBuffer buf = new StringBuffer(); Printer.appendString(buf, (String) cst); pw.print(buf.toString()); } else if (cst instanceof Float) { Float f = (Float) cst; if (f.isNaN() || f.isInfinite()) { pw.print("0.0"); // TODO Jasmin bug workaround } else { pw.print(f); } } else if (cst instanceof Double) { Double d = (Double) cst; if (d.isNaN() || d.isInfinite()) { pw.print("0.0"); // TODO Jasmin bug workaround } else { pw.print(d); } } else { pw.print(cst); } } protected void print(final Label l) { String name = labelNames.get(l); if (name == null) { name = "L" + labelNames.size(); labelNames.put(l, name); } pw.print(name); } protected void print(final LabelNode l) { print(l.getLabel()); } protected void printAnnotations(final List annotations, int visible) { if (annotations != null) { for (int j = 0; j < annotations.size(); ++j) { printAnnotation(annotations.get(j), visible, -1); } } } protected void printAnnotation(final AnnotationNode n, final int visible, final int param) { pw.print(".annotation "); if (visible > 0) { if (param == -1) { pw.print(visible == 1 ? "visible " : "invisible "); } else { pw.print(visible == 1 ? "visibleparam " : "invisibleparam "); pw.print(param); pw.print(' '); } pw.print(n.desc); } pw.println(); if (n.values != null) { for (int i = 0; i < n.values.size(); i += 2) { pw.print(n.values.get(i)); pw.print(' '); printAnnotationValue(n.values.get(i + 1)); } } pw.println(".end annotation"); } protected void printAnnotationValue(final Object value) { if (value instanceof String[]) { pw.print("e "); pw.print(((String[]) value)[0]); pw.print(" = "); print(((String[]) value)[1]); pw.println(); } else if (value instanceof AnnotationNode) { pw.print("@ "); pw.print(((AnnotationNode) value).desc); pw.print(" = "); printAnnotation((AnnotationNode) value, 0, -1); } else if (value instanceof byte[]) { pw.print("[B = "); byte[] v = (byte[]) value; for (int i = 0; i < v.length; i++) { pw.print(v[i]); pw.print(' '); } pw.println(); } else if (value instanceof boolean[]) { pw.print("[Z = "); boolean[] v = (boolean[]) value; for (int i = 0; i < v.length; i++) { pw.print(v[i] ? '1' : '0'); pw.print(' '); } pw.println(); } else if (value instanceof short[]) { pw.print("[S = "); short[] v = (short[]) value; for (int i = 0; i < v.length; i++) { pw.print(v[i]); pw.print(' '); } pw.println(); } else if (value instanceof char[]) { pw.print("[C = "); char[] v = (char[]) value; for (int i = 0; i < v.length; i++) { pw.print(new Integer(v[i])); pw.print(' '); } pw.println(); } else if (value instanceof int[]) { pw.print("[I = "); int[] v = (int[]) value; for (int i = 0; i < v.length; i++) { pw.print(v[i]); pw.print(' '); } pw.println(); } else if (value instanceof long[]) { pw.print("[J = "); long[] v = (long[]) value; for (int i = 0; i < v.length; i++) { pw.print(v[i]); pw.print(' '); } pw.println(); } else if (value instanceof float[]) { pw.print("[F = "); float[] v = (float[]) value; for (int i = 0; i < v.length; i++) { print(new Float(v[i])); pw.print(' '); } pw.println(); } else if (value instanceof double[]) { pw.print("[D = "); double[] v = (double[]) value; for (int i = 0; i < v.length; i++) { print(new Double(v[i])); pw.print(' '); } pw.println(); } else if (value instanceof List) { List l = (List) value; if (l.size() > 0) { Object o = l.get(0); if (o instanceof String[]) { pw.print("[e "); pw.print(((String[]) o)[0]); pw.print(" = "); } else if (o instanceof AnnotationNode) { pw.print("[& "); pw.print(((AnnotationNode) o).desc); pw.print(" = "); pw.print("[@ = "); } else if (o instanceof String) { pw.print("[s = "); } else if (o instanceof Byte) { pw.print("[B = "); } else if (o instanceof Boolean) { pw.print("[Z = "); } else if (o instanceof Character) { pw.print("[C = "); } else if (o instanceof Short) { pw.print("[S = "); } else if (o instanceof Type) { pw.print("[c = "); } else if (o instanceof Integer) { pw.print("[I = "); } else if (o instanceof Float) { pw.print("[F = "); } else if (o instanceof Long) { pw.print("[J = "); } else if (o instanceof Double) { pw.print("[D = "); } for (int j = 0; j < l.size(); ++j) { printAnnotationArrayValue(l.get(j)); pw.print(' '); } } else { pw.print("; empty array annotation value"); } pw.println(); } else if (value instanceof String) { pw.print("s = "); print(value); pw.println(); } else if (value instanceof Byte) { pw.print("B = "); pw.println(((Byte) value).intValue()); } else if (value instanceof Boolean) { pw.print("Z = "); pw.println(((Boolean) value).booleanValue() ? 1 : 0); } else if (value instanceof Character) { pw.print("C = "); pw.println(new Integer(((Character) value).charValue())); } else if (value instanceof Short) { pw.print("S = "); pw.println(((Short) value).intValue()); } else if (value instanceof Type) { pw.print("c = "); pw.println(((Type) value).getDescriptor()); } else if (value instanceof Integer) { pw.print("I = "); print(value); pw.println(); } else if (value instanceof Float) { pw.print("F = "); print(value); pw.println(); } else if (value instanceof Long) { pw.print("J = "); print(value); pw.println(); } else if (value instanceof Double) { pw.print("D = "); print(value); pw.println(); } else { throw new RuntimeException(); } } protected void printAnnotationArrayValue(final Object value) { if (value instanceof String[]) { print(((String[]) value)[1]); } else if (value instanceof AnnotationNode) { printAnnotation((AnnotationNode) value, 0, -1); } else if (value instanceof String) { print(value); } else if (value instanceof Byte) { pw.print(((Byte) value).intValue()); } else if (value instanceof Boolean) { pw.print(((Boolean) value).booleanValue() ? 1 : 0); } else if (value instanceof Character) { pw.print(new Integer(((Character) value).charValue())); } else if (value instanceof Short) { pw.print(((Short) value).intValue()); } else if (value instanceof Type) { pw.print(((Type) value).getDescriptor()); } else { print(value); } } protected void printFrameType(final Object type) { if (type == Opcodes.TOP) { pw.print("Top"); } else if (type == Opcodes.INTEGER) { pw.print("Integer"); } else if (type == Opcodes.FLOAT) { pw.print("Float"); } else if (type == Opcodes.LONG) { pw.print("Long"); } else if (type == Opcodes.DOUBLE) { pw.print("Double"); } else if (type == Opcodes.NULL) { pw.print("Null"); } else if (type == Opcodes.UNINITIALIZED_THIS) { pw.print("UninitializedThis"); } else if (type instanceof Label) { pw.print("Uninitialized "); print((Label) type); } else { pw.print("Object "); pw.print(type); } } } libasm4-java-4.1/examples/jasmin/test/000077500000000000000000000000001207310427500177075ustar00rootroot00000000000000libasm4-java-4.1/examples/jasmin/test/JasminifierClassAdapterTest.java000066400000000000000000000225021207310427500261420ustar00rootroot00000000000000/*** * ASM tests * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ import jas.jasError; import jasmin.ClassFile; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.PrintWriter; import java.io.StringReader; import java.io.StringWriter; import java.util.Arrays; import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import junit.framework.TestCase; import junit.framework.TestSuite; import org.objectweb.asm.Attribute; import org.objectweb.asm.ByteVector; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; import org.objectweb.asm.util.TraceClassVisitor; class ClassFilter extends ClassVisitor { public ClassFilter() { super(Opcodes.ASM4, null); } public void setNext(final ClassVisitor cv) { this.cv = cv; } } class Comment extends Attribute { public Comment() { super("Comment"); } @Override public boolean isUnknown() { return false; } @Override protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, final int codeOff, final Label[] labels) { return new Comment(); } @Override protected ByteVector write(final ClassWriter cw, final byte[] code, final int len, final int maxStack, final int maxLocals) { return new ByteVector(); } } class CodeComment extends Attribute { public CodeComment() { super("CodeComment"); } @Override public boolean isUnknown() { return false; } @Override public boolean isCodeAttribute() { return true; } @Override protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, final int codeOff, final Label[] labels) { return new CodeComment(); } @Override protected ByteVector write(final ClassWriter cw, final byte[] code, final int len, final int maxStack, final int maxLocals) { return new ByteVector(); } @Override protected Label[] getLabels() { super.getLabels(); return new Label[] { new Label() }; } } /** * JasminifierAdapterTest tests. * * @author Eric Bruneton */ public class JasminifierClassAdapterTest extends TestCase { protected String n; protected InputStream is; public static TestSuite suite() throws Exception { return new JasminifierClassAdapterTest().getSuite(); } public JasminifierClassAdapterTest() { super("test"); } protected void init(final String n, final InputStream is) { this.n = n; this.is = is; } protected TestSuite getSuite() throws Exception { TestSuite suite = new TestSuite(getClass().getName()); String files = System.getProperty("asm.test") + ","; String clazz = System.getProperty("asm.test.class"); String partcount = System.getProperty("parts"); String partid = System.getProperty("part"); int parts = partcount == null ? 1 : Integer.parseInt(partcount); int part = partid == null ? 0 : Integer.parseInt(partid); int id = 0; while (files.indexOf(',') != -1) { String file = files.substring(0, files.indexOf(',')); files = files.substring(files.indexOf(',') + 1); File f = new File(file); if (f.isDirectory()) { scanDirectory("", f, suite, clazz); } else { ZipFile zip = new ZipFile(file); Enumeration entries = zip.entries(); while (entries.hasMoreElements()) { ZipEntry e = entries.nextElement(); String n = e.getName(); String p = n.replace('/', '.'); System.out.println(n + " " + clazz); if (n.endsWith(".class") && (clazz == null || p.indexOf(clazz) != -1)) { n = p.substring(0, p.length() - 6); if (id % parts == part) { JasminifierClassAdapterTest t; InputStream is = zip.getInputStream(e); t = new JasminifierClassAdapterTest(); t.init(n, is); suite.addTest(t); } ++id; } } } } return suite; } private void scanDirectory(final String path, final File f, final TestSuite suite, final String clazz) throws Exception { File[] fs = f.listFiles(); for (int i = 0; i < fs.length; ++i) { String n = fs[i].getName(); String qn = path.length() == 0 ? n : path + "." + n; if (fs[i].isDirectory()) { scanDirectory(qn, fs[i], suite, clazz); } else if (qn.endsWith(".class") && (clazz == null || qn.indexOf(clazz) != -1)) { qn = qn.substring(0, qn.length() - 6); InputStream is = new FileInputStream(fs[i]); JasminifierClassAdapterTest t; t = new JasminifierClassAdapterTest(); t.init(qn, is); suite.addTest(t); } } } public void assertEquals(final ClassReader cr1, final ClassReader cr2) throws Exception { assertEquals(cr1, cr2, null, null); } public void assertEquals(final ClassReader cr1, final ClassReader cr2, final ClassFilter filter1, final ClassFilter filter2) throws Exception { if (!Arrays.equals(cr1.b, cr2.b)) { StringWriter sw1 = new StringWriter(); StringWriter sw2 = new StringWriter(); ClassVisitor cv1 = new TraceClassVisitor(new PrintWriter(sw1)); ClassVisitor cv2 = new TraceClassVisitor(new PrintWriter(sw2)); if (filter1 != null) { filter1.setNext(cv1); } if (filter2 != null) { filter2.setNext(cv2); } cr1.accept(filter1 == null ? cv1 : filter1, 0); cr2.accept(filter2 == null ? cv2 : filter2, 0); String s1 = sw1.toString(); String s2 = sw2.toString(); assertEquals("different data", s1, s2); } } @Override public String getName() { return super.getName() + ": " + n; } public void test() throws Exception { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); ClassReader cr = new ClassReader(is); ClassWriter cw = new ClassWriter(0); ClassVisitor cv = new JasminifierClassAdapter(pw, cw); cr.accept(cv, new Attribute[] { new Comment(), new CodeComment() }, ClassReader.EXPAND_FRAMES); pw.close(); String jasmin = sw.toString(); ClassFile cf = new ClassFile(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); cf.readJasmin(new StringReader(jasmin), "test", false); if (cf.errorCount() != 0) { throw new jasError(); } cf.write(bos); bos.close(); assertEquals(cr, new ClassReader(bos.toByteArray()), new ClassFilter() { @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { access |= Opcodes.ACC_SUPER; // Jasmin bug workaround super.visit(version, access, name, signature, superName, interfaces); } }, null); } } libasm4-java-4.1/examples/jasmin/test/build.xml000066400000000000000000000056521207310427500215400ustar00rootroot00000000000000 libasm4-java-4.1/examples/jbfc/000077500000000000000000000000001207310427500163535ustar00rootroot00000000000000libasm4-java-4.1/examples/jbfc/etc/000077500000000000000000000000001207310427500171265ustar00rootroot00000000000000libasm4-java-4.1/examples/jbfc/etc/execute.properties000066400000000000000000000035031207310427500227070ustar00rootroot00000000000000############################################################################### #ASM: a very small and fast Java bytecode manipulation framework #Copyright (c) 2000-2011 INRIA, France Telecom #All rights reserved. # #Redistribution and use in source and binary forms, with or without #modification, are permitted provided that the following conditions #are met: #1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. #2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. #3. Neither the name of the copyright holders nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" #AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE #IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE #ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS #INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN #CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) #ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF #THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### run.classname org.objectweb.asm.jbfc.BFCompilerTest run.parameters libasm4-java-4.1/examples/jbfc/src/000077500000000000000000000000001207310427500171425ustar00rootroot00000000000000libasm4-java-4.1/examples/jbfc/src/jbfc.java000066400000000000000000000062351207310427500207170ustar00rootroot00000000000000/*** * ASM examples: examples showing how ASM can be used * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.jbfc.BFCompiler; import org.objectweb.asm.util.TraceClassVisitor; /** * A naive implementation of compiler for Brain**** language. * http://www.muppetlabs.com/~breadbox/bf/ * * * @author Eugene Kuleshov */ public class jbfc { public static void main(final String[] args) throws IOException { if (args.length < 2) { System.out .println("Usage: jbfc [-v] "); return; } boolean verbose = false; String fileName = null; String className = null; for (int i = 0; i < args.length; i++) { if ("-v".equals(args[i])) { verbose = true; } else { fileName = args[i]; className = args[i + 1]; break; } } FileReader r = new FileReader(fileName); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); BFCompiler c = new BFCompiler(); if (verbose) { c.compile(r, className, fileName, new TraceClassVisitor(cw, new PrintWriter(System.out))); } else { c.compile(r, className, fileName, cw); } r.close(); FileOutputStream os = new FileOutputStream(className + ".class"); os.write(cw.toByteArray()); os.flush(); os.close(); } } libasm4-java-4.1/examples/jbfc/src/org/000077500000000000000000000000001207310427500177315ustar00rootroot00000000000000libasm4-java-4.1/examples/jbfc/src/org/objectweb/000077500000000000000000000000001207310427500216755ustar00rootroot00000000000000libasm4-java-4.1/examples/jbfc/src/org/objectweb/asm/000077500000000000000000000000001207310427500224555ustar00rootroot00000000000000libasm4-java-4.1/examples/jbfc/src/org/objectweb/asm/jbfc/000077500000000000000000000000001207310427500233615ustar00rootroot00000000000000libasm4-java-4.1/examples/jbfc/src/org/objectweb/asm/jbfc/BFCompiler.java000066400000000000000000000152371207310427500262160ustar00rootroot00000000000000/*** * ASM examples: examples showing how ASM can be used * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.objectweb.asm.jbfc; import java.io.IOException; import java.io.Reader; import java.util.Stack; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; /** * A naive implementation of compiler for Brain**** language. * http://www.muppetlabs.com/~breadbox/bf/ * * * @author Eugene Kuleshov */ public class BFCompiler implements Opcodes { private static final int V_IS = 0; private static final int V_OS = 1; private static final int V_P = 2; private static final int V_D = 3; public void compile(final Reader r, final String className, final String sourceName, final ClassVisitor cv) throws IOException { cv.visit(Opcodes.V1_3, ACC_PUBLIC, className.replace('.', '/'), null, "java/lang/Object", null); cv.visitSource(sourceName, null); MethodVisitor mv; { mv = cv.visitMethod(ACC_PUBLIC, "", "()V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V"); mv.visitInsn(RETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } { // Init local vars for BF environment: // 0 InputStream // 1 OutputStream // 2 Data Pointer // 3 Data Array (int[ 30000]) mv = cv.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null); mv.visitCode(); mv.visitFieldInsn(GETSTATIC, "java/lang/System", "in", "Ljava/io/InputStream;"); mv.visitVarInsn(ASTORE, V_IS); mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitVarInsn(ASTORE, V_OS); mv.visitInsn(ICONST_0); mv.visitVarInsn(ISTORE, V_P); mv.visitIntInsn(SIPUSH, 30000); mv.visitIntInsn(NEWARRAY, T_INT); mv.visitVarInsn(ASTORE, V_D); Stack

    *
  • The constant pool from the original class is copied as is in the new * class, which saves time. New constant pool entries will be added at the * end if necessary, but unused constant pool entries won't be * removed.
  • *
  • Methods that are not transformed are copied as is in the new class, * directly from the original class bytecode (i.e. without emitting visit * events for all the method instructions), which saves a lot of * time. Untransformed methods are detected by the fact that the * {@link ClassReader} receives {@link MethodVisitor} objects that come from * a {@link ClassWriter} (and not from any other {@link ClassVisitor} * instance).
  • *
* * @param classReader * the {@link ClassReader} used to read the original class. It * will be used to copy the entire constant pool from the * original class and also to copy other fragments of original * bytecode where applicable. * @param flags * option flags that can be used to modify the default behavior * of this class. These option flags do not affect methods * that are copied as is in the new class. This means that the * maximum stack size nor the stack frames will be computed for * these methods. See {@link #COMPUTE_MAXS}, * {@link #COMPUTE_FRAMES}. */ public ClassWriter(final ClassReader classReader, final int flags) { this(flags); classReader.copyPool(this); this.cr = classReader; } // ------------------------------------------------------------------------ // Implementation of the ClassVisitor abstract class // ------------------------------------------------------------------------ @Override public final void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) { this.version = version; this.access = access; this.name = newClass(name); thisName = name; if (ClassReader.SIGNATURES && signature != null) { this.signature = newUTF8(signature); } this.superName = superName == null ? 0 : newClass(superName); if (interfaces != null && interfaces.length > 0) { interfaceCount = interfaces.length; this.interfaces = new int[interfaceCount]; for (int i = 0; i < interfaceCount; ++i) { this.interfaces[i] = newClass(interfaces[i]); } } } @Override public final void visitSource(final String file, final String debug) { if (file != null) { sourceFile = newUTF8(file); } if (debug != null) { sourceDebug = new ByteVector().putUTF8(debug); } } @Override public final void visitOuterClass(final String owner, final String name, final String desc) { enclosingMethodOwner = newClass(owner); if (name != null && desc != null) { enclosingMethod = newNameType(name, desc); } } @Override public final AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { if (!ClassReader.ANNOTATIONS) { return null; } ByteVector bv = new ByteVector(); // write type, and reserve space for values count bv.putShort(newUTF8(desc)).putShort(0); AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2); if (visible) { aw.next = anns; anns = aw; } else { aw.next = ianns; ianns = aw; } return aw; } @Override public final void visitAttribute(final Attribute attr) { attr.next = attrs; attrs = attr; } @Override public final void visitInnerClass(final String name, final String outerName, final String innerName, final int access) { if (innerClasses == null) { innerClasses = new ByteVector(); } ++innerClassesCount; innerClasses.putShort(name == null ? 0 : newClass(name)); innerClasses.putShort(outerName == null ? 0 : newClass(outerName)); innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName)); innerClasses.putShort(access); } @Override public final FieldVisitor visitField(final int access, final String name, final String desc, final String signature, final Object value) { return new FieldWriter(this, access, name, desc, signature, value); } @Override public final MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { return new MethodWriter(this, access, name, desc, signature, exceptions, computeMaxs, computeFrames); } @Override public final void visitEnd() { } // ------------------------------------------------------------------------ // Other public methods // ------------------------------------------------------------------------ /** * Returns the bytecode of the class that was build with this class writer. * * @return the bytecode of the class that was build with this class writer. */ public byte[] toByteArray() { if (index > 0xFFFF) { throw new RuntimeException("Class file too large!"); } // computes the real size of the bytecode of this class int size = 24 + 2 * interfaceCount; int nbFields = 0; FieldWriter fb = firstField; while (fb != null) { ++nbFields; size += fb.getSize(); fb = (FieldWriter) fb.fv; } int nbMethods = 0; MethodWriter mb = firstMethod; while (mb != null) { ++nbMethods; size += mb.getSize(); mb = (MethodWriter) mb.mv; } int attributeCount = 0; if (bootstrapMethods != null) { // we put it as first attribute in order to improve a bit // ClassReader.copyBootstrapMethods ++attributeCount; size += 8 + bootstrapMethods.length; newUTF8("BootstrapMethods"); } if (ClassReader.SIGNATURES && signature != 0) { ++attributeCount; size += 8; newUTF8("Signature"); } if (sourceFile != 0) { ++attributeCount; size += 8; newUTF8("SourceFile"); } if (sourceDebug != null) { ++attributeCount; size += sourceDebug.length + 4; newUTF8("SourceDebugExtension"); } if (enclosingMethodOwner != 0) { ++attributeCount; size += 10; newUTF8("EnclosingMethod"); } if ((access & Opcodes.ACC_DEPRECATED) != 0) { ++attributeCount; size += 6; newUTF8("Deprecated"); } if ((access & Opcodes.ACC_SYNTHETIC) != 0) { if ((version & 0xFFFF) < Opcodes.V1_5 || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) { ++attributeCount; size += 6; newUTF8("Synthetic"); } } if (innerClasses != null) { ++attributeCount; size += 8 + innerClasses.length; newUTF8("InnerClasses"); } if (ClassReader.ANNOTATIONS && anns != null) { ++attributeCount; size += 8 + anns.getSize(); newUTF8("RuntimeVisibleAnnotations"); } if (ClassReader.ANNOTATIONS && ianns != null) { ++attributeCount; size += 8 + ianns.getSize(); newUTF8("RuntimeInvisibleAnnotations"); } if (attrs != null) { attributeCount += attrs.getCount(); size += attrs.getSize(this, null, 0, -1, -1); } size += pool.length; // allocates a byte vector of this size, in order to avoid unnecessary // arraycopy operations in the ByteVector.enlarge() method ByteVector out = new ByteVector(size); out.putInt(0xCAFEBABE).putInt(version); out.putShort(index).putByteArray(pool.data, 0, pool.length); int mask = Opcodes.ACC_DEPRECATED | ACC_SYNTHETIC_ATTRIBUTE | ((access & ACC_SYNTHETIC_ATTRIBUTE) / TO_ACC_SYNTHETIC); out.putShort(access & ~mask).putShort(name).putShort(superName); out.putShort(interfaceCount); for (int i = 0; i < interfaceCount; ++i) { out.putShort(interfaces[i]); } out.putShort(nbFields); fb = firstField; while (fb != null) { fb.put(out); fb = (FieldWriter) fb.fv; } out.putShort(nbMethods); mb = firstMethod; while (mb != null) { mb.put(out); mb = (MethodWriter) mb.mv; } out.putShort(attributeCount); if (bootstrapMethods != null) { out.putShort(newUTF8("BootstrapMethods")); out.putInt(bootstrapMethods.length + 2).putShort( bootstrapMethodsCount); out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length); } if (ClassReader.SIGNATURES && signature != 0) { out.putShort(newUTF8("Signature")).putInt(2).putShort(signature); } if (sourceFile != 0) { out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile); } if (sourceDebug != null) { int len = sourceDebug.length - 2; out.putShort(newUTF8("SourceDebugExtension")).putInt(len); out.putByteArray(sourceDebug.data, 2, len); } if (enclosingMethodOwner != 0) { out.putShort(newUTF8("EnclosingMethod")).putInt(4); out.putShort(enclosingMethodOwner).putShort(enclosingMethod); } if ((access & Opcodes.ACC_DEPRECATED) != 0) { out.putShort(newUTF8("Deprecated")).putInt(0); } if ((access & Opcodes.ACC_SYNTHETIC) != 0) { if ((version & 0xFFFF) < Opcodes.V1_5 || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) { out.putShort(newUTF8("Synthetic")).putInt(0); } } if (innerClasses != null) { out.putShort(newUTF8("InnerClasses")); out.putInt(innerClasses.length + 2).putShort(innerClassesCount); out.putByteArray(innerClasses.data, 0, innerClasses.length); } if (ClassReader.ANNOTATIONS && anns != null) { out.putShort(newUTF8("RuntimeVisibleAnnotations")); anns.put(out); } if (ClassReader.ANNOTATIONS && ianns != null) { out.putShort(newUTF8("RuntimeInvisibleAnnotations")); ianns.put(out); } if (attrs != null) { attrs.put(this, null, 0, -1, -1, out); } if (invalidFrames) { ClassWriter cw = new ClassWriter(COMPUTE_FRAMES); new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES); return cw.toByteArray(); } return out.data; } // ------------------------------------------------------------------------ // Utility methods: constant pool management // ------------------------------------------------------------------------ /** * Adds a number or string constant to the constant pool of the class being * build. Does nothing if the constant pool already contains a similar item. * * @param cst * the value of the constant to be added to the constant pool. * This parameter must be an {@link Integer}, a {@link Float}, a * {@link Long}, a {@link Double}, a {@link String} or a * {@link Type}. * @return a new or already existing constant item with the given value. */ Item newConstItem(final Object cst) { if (cst instanceof Integer) { int val = ((Integer) cst).intValue(); return newInteger(val); } else if (cst instanceof Byte) { int val = ((Byte) cst).intValue(); return newInteger(val); } else if (cst instanceof Character) { int val = ((Character) cst).charValue(); return newInteger(val); } else if (cst instanceof Short) { int val = ((Short) cst).intValue(); return newInteger(val); } else if (cst instanceof Boolean) { int val = ((Boolean) cst).booleanValue() ? 1 : 0; return newInteger(val); } else if (cst instanceof Float) { float val = ((Float) cst).floatValue(); return newFloat(val); } else if (cst instanceof Long) { long val = ((Long) cst).longValue(); return newLong(val); } else if (cst instanceof Double) { double val = ((Double) cst).doubleValue(); return newDouble(val); } else if (cst instanceof String) { return newString((String) cst); } else if (cst instanceof Type) { Type t = (Type) cst; int s = t.getSort(); if (s == Type.OBJECT) { return newClassItem(t.getInternalName()); } else if (s == Type.METHOD) { return newMethodTypeItem(t.getDescriptor()); } else { // s == primitive type or array return newClassItem(t.getDescriptor()); } } else if (cst instanceof Handle) { Handle h = (Handle) cst; return newHandleItem(h.tag, h.owner, h.name, h.desc); } else { throw new IllegalArgumentException("value " + cst); } } /** * Adds a number or string constant to the constant pool of the class being * build. Does nothing if the constant pool already contains a similar item. * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * * @param cst * the value of the constant to be added to the constant pool. * This parameter must be an {@link Integer}, a {@link Float}, a * {@link Long}, a {@link Double} or a {@link String}. * @return the index of a new or already existing constant item with the * given value. */ public int newConst(final Object cst) { return newConstItem(cst).index; } /** * Adds an UTF8 string to the constant pool of the class being build. Does * nothing if the constant pool already contains a similar item. This * method is intended for {@link Attribute} sub classes, and is normally not * needed by class generators or adapters. * * @param value * the String value. * @return the index of a new or already existing UTF8 item. */ public int newUTF8(final String value) { key.set(UTF8, value, null, null); Item result = get(key); if (result == null) { pool.putByte(UTF8).putUTF8(value); result = new Item(index++, key); put(result); } return result.index; } /** * Adds a class reference to the constant pool of the class being build. * Does nothing if the constant pool already contains a similar item. * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * * @param value * the internal name of the class. * @return a new or already existing class reference item. */ Item newClassItem(final String value) { key2.set(CLASS, value, null, null); Item result = get(key2); if (result == null) { pool.put12(CLASS, newUTF8(value)); result = new Item(index++, key2); put(result); } return result; } /** * Adds a class reference to the constant pool of the class being build. * Does nothing if the constant pool already contains a similar item. * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * * @param value * the internal name of the class. * @return the index of a new or already existing class reference item. */ public int newClass(final String value) { return newClassItem(value).index; } /** * Adds a method type reference to the constant pool of the class being * build. Does nothing if the constant pool already contains a similar item. * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * * @param methodDesc * method descriptor of the method type. * @return a new or already existing method type reference item. */ Item newMethodTypeItem(final String methodDesc) { key2.set(MTYPE, methodDesc, null, null); Item result = get(key2); if (result == null) { pool.put12(MTYPE, newUTF8(methodDesc)); result = new Item(index++, key2); put(result); } return result; } /** * Adds a method type reference to the constant pool of the class being * build. Does nothing if the constant pool already contains a similar item. * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * * @param methodDesc * method descriptor of the method type. * @return the index of a new or already existing method type reference * item. */ public int newMethodType(final String methodDesc) { return newMethodTypeItem(methodDesc).index; } /** * Adds a handle to the constant pool of the class being build. Does nothing * if the constant pool already contains a similar item. This method is * intended for {@link Attribute} sub classes, and is normally not needed by * class generators or adapters. * * @param tag * the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, * {@link Opcodes#H_INVOKESTATIC}, * {@link Opcodes#H_INVOKESPECIAL}, * {@link Opcodes#H_NEWINVOKESPECIAL} or * {@link Opcodes#H_INVOKEINTERFACE}. * @param owner * the internal name of the field or method owner class. * @param name * the name of the field or method. * @param desc * the descriptor of the field or method. * @return a new or an already existing method type reference item. */ Item newHandleItem(final int tag, final String owner, final String name, final String desc) { key4.set(HANDLE_BASE + tag, owner, name, desc); Item result = get(key4); if (result == null) { if (tag <= Opcodes.H_PUTSTATIC) { put112(HANDLE, tag, newField(owner, name, desc)); } else { put112(HANDLE, tag, newMethod(owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE)); } result = new Item(index++, key4); put(result); } return result; } /** * Adds a handle to the constant pool of the class being build. Does nothing * if the constant pool already contains a similar item. This method is * intended for {@link Attribute} sub classes, and is normally not needed by * class generators or adapters. * * @param tag * the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, * {@link Opcodes#H_INVOKESTATIC}, * {@link Opcodes#H_INVOKESPECIAL}, * {@link Opcodes#H_NEWINVOKESPECIAL} or * {@link Opcodes#H_INVOKEINTERFACE}. * @param owner * the internal name of the field or method owner class. * @param name * the name of the field or method. * @param desc * the descriptor of the field or method. * @return the index of a new or already existing method type reference * item. */ public int newHandle(final int tag, final String owner, final String name, final String desc) { return newHandleItem(tag, owner, name, desc).index; } /** * Adds an invokedynamic reference to the constant pool of the class being * build. Does nothing if the constant pool already contains a similar item. * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * * @param name * name of the invoked method. * @param desc * descriptor of the invoke method. * @param bsm * the bootstrap method. * @param bsmArgs * the bootstrap method constant arguments. * * @return a new or an already existing invokedynamic type reference item. */ Item newInvokeDynamicItem(final String name, final String desc, final Handle bsm, final Object... bsmArgs) { // cache for performance ByteVector bootstrapMethods = this.bootstrapMethods; if (bootstrapMethods == null) { bootstrapMethods = this.bootstrapMethods = new ByteVector(); } int position = bootstrapMethods.length; // record current position int hashCode = bsm.hashCode(); bootstrapMethods.putShort(newHandle(bsm.tag, bsm.owner, bsm.name, bsm.desc)); int argsLength = bsmArgs.length; bootstrapMethods.putShort(argsLength); for (int i = 0; i < argsLength; i++) { Object bsmArg = bsmArgs[i]; hashCode ^= bsmArg.hashCode(); bootstrapMethods.putShort(newConst(bsmArg)); } byte[] data = bootstrapMethods.data; int length = (1 + 1 + argsLength) << 1; // (bsm + argCount + arguments) hashCode &= 0x7FFFFFFF; Item result = items[hashCode % items.length]; loop: while (result != null) { if (result.type != BSM || result.hashCode != hashCode) { result = result.next; continue; } // because the data encode the size of the argument // we don't need to test if these size are equals int resultPosition = result.intVal; for (int p = 0; p < length; p++) { if (data[position + p] != data[resultPosition + p]) { result = result.next; continue loop; } } break; } int bootstrapMethodIndex; if (result != null) { bootstrapMethodIndex = result.index; bootstrapMethods.length = position; // revert to old position } else { bootstrapMethodIndex = bootstrapMethodsCount++; result = new Item(bootstrapMethodIndex); result.set(position, hashCode); put(result); } // now, create the InvokeDynamic constant key3.set(name, desc, bootstrapMethodIndex); result = get(key3); if (result == null) { put122(INDY, bootstrapMethodIndex, newNameType(name, desc)); result = new Item(index++, key3); put(result); } return result; } /** * Adds an invokedynamic reference to the constant pool of the class being * build. Does nothing if the constant pool already contains a similar item. * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * * @param name * name of the invoked method. * @param desc * descriptor of the invoke method. * @param bsm * the bootstrap method. * @param bsmArgs * the bootstrap method constant arguments. * * @return the index of a new or already existing invokedynamic reference * item. */ public int newInvokeDynamic(final String name, final String desc, final Handle bsm, final Object... bsmArgs) { return newInvokeDynamicItem(name, desc, bsm, bsmArgs).index; } /** * Adds a field reference to the constant pool of the class being build. * Does nothing if the constant pool already contains a similar item. * * @param owner * the internal name of the field's owner class. * @param name * the field's name. * @param desc * the field's descriptor. * @return a new or already existing field reference item. */ Item newFieldItem(final String owner, final String name, final String desc) { key3.set(FIELD, owner, name, desc); Item result = get(key3); if (result == null) { put122(FIELD, newClass(owner), newNameType(name, desc)); result = new Item(index++, key3); put(result); } return result; } /** * Adds a field reference to the constant pool of the class being build. * Does nothing if the constant pool already contains a similar item. * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * * @param owner * the internal name of the field's owner class. * @param name * the field's name. * @param desc * the field's descriptor. * @return the index of a new or already existing field reference item. */ public int newField(final String owner, final String name, final String desc) { return newFieldItem(owner, name, desc).index; } /** * Adds a method reference to the constant pool of the class being build. * Does nothing if the constant pool already contains a similar item. * * @param owner * the internal name of the method's owner class. * @param name * the method's name. * @param desc * the method's descriptor. * @param itf * true if owner is an interface. * @return a new or already existing method reference item. */ Item newMethodItem(final String owner, final String name, final String desc, final boolean itf) { int type = itf ? IMETH : METH; key3.set(type, owner, name, desc); Item result = get(key3); if (result == null) { put122(type, newClass(owner), newNameType(name, desc)); result = new Item(index++, key3); put(result); } return result; } /** * Adds a method reference to the constant pool of the class being build. * Does nothing if the constant pool already contains a similar item. * This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters. * * @param owner * the internal name of the method's owner class. * @param name * the method's name. * @param desc * the method's descriptor. * @param itf * true if owner is an interface. * @return the index of a new or already existing method reference item. */ public int newMethod(final String owner, final String name, final String desc, final boolean itf) { return newMethodItem(owner, name, desc, itf).index; } /** * Adds an integer to the constant pool of the class being build. Does * nothing if the constant pool already contains a similar item. * * @param value * the int value. * @return a new or already existing int item. */ Item newInteger(final int value) { key.set(value); Item result = get(key); if (result == null) { pool.putByte(INT).putInt(value); result = new Item(index++, key); put(result); } return result; } /** * Adds a float to the constant pool of the class being build. Does nothing * if the constant pool already contains a similar item. * * @param value * the float value. * @return a new or already existing float item. */ Item newFloat(final float value) { key.set(value); Item result = get(key); if (result == null) { pool.putByte(FLOAT).putInt(key.intVal); result = new Item(index++, key); put(result); } return result; } /** * Adds a long to the constant pool of the class being build. Does nothing * if the constant pool already contains a similar item. * * @param value * the long value. * @return a new or already existing long item. */ Item newLong(final long value) { key.set(value); Item result = get(key); if (result == null) { pool.putByte(LONG).putLong(value); result = new Item(index, key); index += 2; put(result); } return result; } /** * Adds a double to the constant pool of the class being build. Does nothing * if the constant pool already contains a similar item. * * @param value * the double value. * @return a new or already existing double item. */ Item newDouble(final double value) { key.set(value); Item result = get(key); if (result == null) { pool.putByte(DOUBLE).putLong(key.longVal); result = new Item(index, key); index += 2; put(result); } return result; } /** * Adds a string to the constant pool of the class being build. Does nothing * if the constant pool already contains a similar item. * * @param value * the String value. * @return a new or already existing string item. */ private Item newString(final String value) { key2.set(STR, value, null, null); Item result = get(key2); if (result == null) { pool.put12(STR, newUTF8(value)); result = new Item(index++, key2); put(result); } return result; } /** * Adds a name and type to the constant pool of the class being build. Does * nothing if the constant pool already contains a similar item. This * method is intended for {@link Attribute} sub classes, and is normally not * needed by class generators or adapters. * * @param name * a name. * @param desc * a type descriptor. * @return the index of a new or already existing name and type item. */ public int newNameType(final String name, final String desc) { return newNameTypeItem(name, desc).index; } /** * Adds a name and type to the constant pool of the class being build. Does * nothing if the constant pool already contains a similar item. * * @param name * a name. * @param desc * a type descriptor. * @return a new or already existing name and type item. */ Item newNameTypeItem(final String name, final String desc) { key2.set(NAME_TYPE, name, desc, null); Item result = get(key2); if (result == null) { put122(NAME_TYPE, newUTF8(name), newUTF8(desc)); result = new Item(index++, key2); put(result); } return result; } /** * Adds the given internal name to {@link #typeTable} and returns its index. * Does nothing if the type table already contains this internal name. * * @param type * the internal name to be added to the type table. * @return the index of this internal name in the type table. */ int addType(final String type) { key.set(TYPE_NORMAL, type, null, null); Item result = get(key); if (result == null) { result = addType(key); } return result.index; } /** * Adds the given "uninitialized" type to {@link #typeTable} and returns its * index. This method is used for UNINITIALIZED types, made of an internal * name and a bytecode offset. * * @param type * the internal name to be added to the type table. * @param offset * the bytecode offset of the NEW instruction that created this * UNINITIALIZED type value. * @return the index of this internal name in the type table. */ int addUninitializedType(final String type, final int offset) { key.type = TYPE_UNINIT; key.intVal = offset; key.strVal1 = type; key.hashCode = 0x7FFFFFFF & (TYPE_UNINIT + type.hashCode() + offset); Item result = get(key); if (result == null) { result = addType(key); } return result.index; } /** * Adds the given Item to {@link #typeTable}. * * @param item * the value to be added to the type table. * @return the added Item, which a new Item instance with the same value as * the given Item. */ private Item addType(final Item item) { ++typeCount; Item result = new Item(typeCount, key); put(result); if (typeTable == null) { typeTable = new Item[16]; } if (typeCount == typeTable.length) { Item[] newTable = new Item[2 * typeTable.length]; System.arraycopy(typeTable, 0, newTable, 0, typeTable.length); typeTable = newTable; } typeTable[typeCount] = result; return result; } /** * Returns the index of the common super type of the two given types. This * method calls {@link #getCommonSuperClass} and caches the result in the * {@link #items} hash table to speedup future calls with the same * parameters. * * @param type1 * index of an internal name in {@link #typeTable}. * @param type2 * index of an internal name in {@link #typeTable}. * @return the index of the common super type of the two given types. */ int getMergedType(final int type1, final int type2) { key2.type = TYPE_MERGED; key2.longVal = type1 | (((long) type2) << 32); key2.hashCode = 0x7FFFFFFF & (TYPE_MERGED + type1 + type2); Item result = get(key2); if (result == null) { String t = typeTable[type1].strVal1; String u = typeTable[type2].strVal1; key2.intVal = addType(getCommonSuperClass(t, u)); result = new Item((short) 0, key2); put(result); } return result.intVal; } /** * Returns the common super type of the two given types. The default * implementation of this method loads the two given classes and uses * the java.lang.Class methods to find the common super class. It can be * overridden to compute this common super type in other ways, in particular * without actually loading any class, or to take into account the class * that is currently being generated by this ClassWriter, which can of * course not be loaded since it is under construction. * * @param type1 * the internal name of a class. * @param type2 * the internal name of another class. * @return the internal name of the common super class of the two given * classes. */ protected String getCommonSuperClass(final String type1, final String type2) { Class c, d; ClassLoader classLoader = getClass().getClassLoader(); try { c = Class.forName(type1.replace('/', '.'), false, classLoader); d = Class.forName(type2.replace('/', '.'), false, classLoader); } catch (Exception e) { throw new RuntimeException(e.toString()); } if (c.isAssignableFrom(d)) { return type1; } if (d.isAssignableFrom(c)) { return type2; } if (c.isInterface() || d.isInterface()) { return "java/lang/Object"; } else { do { c = c.getSuperclass(); } while (!c.isAssignableFrom(d)); return c.getName().replace('.', '/'); } } /** * Returns the constant pool's hash table item which is equal to the given * item. * * @param key * a constant pool item. * @return the constant pool's hash table item which is equal to the given * item, or null if there is no such item. */ private Item get(final Item key) { Item i = items[key.hashCode % items.length]; while (i != null && (i.type != key.type || !key.isEqualTo(i))) { i = i.next; } return i; } /** * Puts the given item in the constant pool's hash table. The hash table * must not already contains this item. * * @param i * the item to be added to the constant pool's hash table. */ private void put(final Item i) { if (index + typeCount > threshold) { int ll = items.length; int nl = ll * 2 + 1; Item[] newItems = new Item[nl]; for (int l = ll - 1; l >= 0; --l) { Item j = items[l]; while (j != null) { int index = j.hashCode % newItems.length; Item k = j.next; j.next = newItems[index]; newItems[index] = j; j = k; } } items = newItems; threshold = (int) (nl * 0.75); } int index = i.hashCode % items.length; i.next = items[index]; items[index] = i; } /** * Puts one byte and two shorts into the constant pool. * * @param b * a byte. * @param s1 * a short. * @param s2 * another short. */ private void put122(final int b, final int s1, final int s2) { pool.put12(b, s1).putShort(s2); } /** * Puts two bytes and one short into the constant pool. * * @param b1 * a byte. * @param b2 * another byte. * @param s * a short. */ private void put112(final int b1, final int b2, final int s) { pool.put11(b1, b2).putShort(s); } } libasm4-java-4.1/src/org/objectweb/asm/Context.java000066400000000000000000000065301207310427500222260ustar00rootroot00000000000000/*** * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.objectweb.asm; /** * Information about a class being parsed in a {@link ClassReader}. * * @author Eric Bruneton */ class Context { /** * Prototypes of the attributes that must be parsed for this class. */ Attribute[] attrs; /** * The {@link ClassReader} option flags for the parsing of this class. */ int flags; /** * The buffer used to read strings. */ char[] buffer; /** * The start index of each bootstrap method. */ int[] bootstrapMethods; /** * The access flags of the method currently being parsed. */ int access; /** * The name of the method currently being parsed. */ String name; /** * The descriptor of the method currently being parsed. */ String desc; /** * The offset of the latest stack map frame that has been parsed. */ int offset; /** * The encoding of the latest stack map frame that has been parsed. */ int mode; /** * The number of locals in the latest stack map frame that has been parsed. */ int localCount; /** * The number locals in the latest stack map frame that has been parsed, * minus the number of locals in the previous frame. */ int localDiff; /** * The local values of the latest stack map frame that has been parsed. */ Object[] local; /** * The stack size of the latest stack map frame that has been parsed. */ int stackCount; /** * The stack values of the latest stack map frame that has been parsed. */ Object[] stack; }libasm4-java-4.1/src/org/objectweb/asm/Edge.java000066400000000000000000000061421207310427500214450ustar00rootroot00000000000000/*** * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.objectweb.asm; /** * An edge in the control flow graph of a method body. See {@link Label Label}. * * @author Eric Bruneton */ class Edge { /** * Denotes a normal control flow graph edge. */ static final int NORMAL = 0; /** * Denotes a control flow graph edge corresponding to an exception handler. * More precisely any {@link Edge} whose {@link #info} is strictly positive * corresponds to an exception handler. The actual value of {@link #info} is * the index, in the {@link ClassWriter} type table, of the exception that * is catched. */ static final int EXCEPTION = 0x7FFFFFFF; /** * Information about this control flow graph edge. If * {@link ClassWriter#COMPUTE_MAXS} is used this field is the (relative) * stack size in the basic block from which this edge originates. This size * is equal to the stack size at the "jump" instruction to which this edge * corresponds, relatively to the stack size at the beginning of the * originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used, * this field is the kind of this control flow graph edge (i.e. NORMAL or * EXCEPTION). */ int info; /** * The successor block of the basic block from which this edge originates. */ Label successor; /** * The next edge in the list of successors of the originating basic block. * See {@link Label#successors successors}. */ Edge next; } libasm4-java-4.1/src/org/objectweb/asm/FieldVisitor.java000066400000000000000000000102461207310427500232040ustar00rootroot00000000000000/*** * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.objectweb.asm; /** * A visitor to visit a Java field. The methods of this class must be called in * the following order: ( visitAnnotation | visitAttribute )* * visitEnd. * * @author Eric Bruneton */ public abstract class FieldVisitor { /** * The ASM API version implemented by this visitor. The value of this field * must be one of {@link Opcodes#ASM4}. */ protected final int api; /** * The field visitor to which this visitor must delegate method calls. May * be null. */ protected FieldVisitor fv; /** * Constructs a new {@link FieldVisitor}. * * @param api * the ASM API version implemented by this visitor. Must be one * of {@link Opcodes#ASM4}. */ public FieldVisitor(final int api) { this(api, null); } /** * Constructs a new {@link FieldVisitor}. * * @param api * the ASM API version implemented by this visitor. Must be one * of {@link Opcodes#ASM4}. * @param fv * the field visitor to which this visitor must delegate method * calls. May be null. */ public FieldVisitor(final int api, final FieldVisitor fv) { if (api != Opcodes.ASM4) { throw new IllegalArgumentException(); } this.api = api; this.fv = fv; } /** * Visits an annotation of the field. * * @param desc * the class descriptor of the annotation class. * @param visible * true if the annotation is visible at runtime. * @return a visitor to visit the annotation values, or null if * this visitor is not interested in visiting this annotation. */ public AnnotationVisitor visitAnnotation(String desc, boolean visible) { if (fv != null) { return fv.visitAnnotation(desc, visible); } return null; } /** * Visits a non standard attribute of the field. * * @param attr * an attribute. */ public void visitAttribute(Attribute attr) { if (fv != null) { fv.visitAttribute(attr); } } /** * Visits the end of the field. This method, which is the last one to be * called, is used to inform the visitor that all the annotations and * attributes of the field have been visited. */ public void visitEnd() { if (fv != null) { fv.visitEnd(); } } } libasm4-java-4.1/src/org/objectweb/asm/FieldWriter.java000066400000000000000000000220111207310427500230120ustar00rootroot00000000000000/*** * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.objectweb.asm; /** * An {@link FieldVisitor} that generates Java fields in bytecode form. * * @author Eric Bruneton */ final class FieldWriter extends FieldVisitor { /** * The class writer to which this field must be added. */ private final ClassWriter cw; /** * Access flags of this field. */ private final int access; /** * The index of the constant pool item that contains the name of this * method. */ private final int name; /** * The index of the constant pool item that contains the descriptor of this * field. */ private final int desc; /** * The index of the constant pool item that contains the signature of this * field. */ private int signature; /** * The index of the constant pool item that contains the constant value of * this field. */ private int value; /** * The runtime visible annotations of this field. May be null. */ private AnnotationWriter anns; /** * The runtime invisible annotations of this field. May be null. */ private AnnotationWriter ianns; /** * The non standard attributes of this field. May be null. */ private Attribute attrs; // ------------------------------------------------------------------------ // Constructor // ------------------------------------------------------------------------ /** * Constructs a new {@link FieldWriter}. * * @param cw * the class writer to which this field must be added. * @param access * the field's access flags (see {@link Opcodes}). * @param name * the field's name. * @param desc * the field's descriptor (see {@link Type}). * @param signature * the field's signature. May be null. * @param value * the field's constant value. May be null. */ FieldWriter(final ClassWriter cw, final int access, final String name, final String desc, final String signature, final Object value) { super(Opcodes.ASM4); if (cw.firstField == null) { cw.firstField = this; } else { cw.lastField.fv = this; } cw.lastField = this; this.cw = cw; this.access = access; this.name = cw.newUTF8(name); this.desc = cw.newUTF8(desc); if (ClassReader.SIGNATURES && signature != null) { this.signature = cw.newUTF8(signature); } if (value != null) { this.value = cw.newConstItem(value).index; } } // ------------------------------------------------------------------------ // Implementation of the FieldVisitor abstract class // ------------------------------------------------------------------------ @Override public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { if (!ClassReader.ANNOTATIONS) { return null; } ByteVector bv = new ByteVector(); // write type, and reserve space for values count bv.putShort(cw.newUTF8(desc)).putShort(0); AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); if (visible) { aw.next = anns; anns = aw; } else { aw.next = ianns; ianns = aw; } return aw; } @Override public void visitAttribute(final Attribute attr) { attr.next = attrs; attrs = attr; } @Override public void visitEnd() { } // ------------------------------------------------------------------------ // Utility methods // ------------------------------------------------------------------------ /** * Returns the size of this field. * * @return the size of this field. */ int getSize() { int size = 8; if (value != 0) { cw.newUTF8("ConstantValue"); size += 8; } if ((access & Opcodes.ACC_SYNTHETIC) != 0) { if ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { cw.newUTF8("Synthetic"); size += 6; } } if ((access & Opcodes.ACC_DEPRECATED) != 0) { cw.newUTF8("Deprecated"); size += 6; } if (ClassReader.SIGNATURES && signature != 0) { cw.newUTF8("Signature"); size += 8; } if (ClassReader.ANNOTATIONS && anns != null) { cw.newUTF8("RuntimeVisibleAnnotations"); size += 8 + anns.getSize(); } if (ClassReader.ANNOTATIONS && ianns != null) { cw.newUTF8("RuntimeInvisibleAnnotations"); size += 8 + ianns.getSize(); } if (attrs != null) { size += attrs.getSize(cw, null, 0, -1, -1); } return size; } /** * Puts the content of this field into the given byte vector. * * @param out * where the content of this field must be put. */ void put(final ByteVector out) { final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC; int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR); out.putShort(access & ~mask).putShort(name).putShort(desc); int attributeCount = 0; if (value != 0) { ++attributeCount; } if ((access & Opcodes.ACC_SYNTHETIC) != 0) { if ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { ++attributeCount; } } if ((access & Opcodes.ACC_DEPRECATED) != 0) { ++attributeCount; } if (ClassReader.SIGNATURES && signature != 0) { ++attributeCount; } if (ClassReader.ANNOTATIONS && anns != null) { ++attributeCount; } if (ClassReader.ANNOTATIONS && ianns != null) { ++attributeCount; } if (attrs != null) { attributeCount += attrs.getCount(); } out.putShort(attributeCount); if (value != 0) { out.putShort(cw.newUTF8("ConstantValue")); out.putInt(2).putShort(value); } if ((access & Opcodes.ACC_SYNTHETIC) != 0) { if ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { out.putShort(cw.newUTF8("Synthetic")).putInt(0); } } if ((access & Opcodes.ACC_DEPRECATED) != 0) { out.putShort(cw.newUTF8("Deprecated")).putInt(0); } if (ClassReader.SIGNATURES && signature != 0) { out.putShort(cw.newUTF8("Signature")); out.putInt(2).putShort(signature); } if (ClassReader.ANNOTATIONS && anns != null) { out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); anns.put(out); } if (ClassReader.ANNOTATIONS && ianns != null) { out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); ianns.put(out); } if (attrs != null) { attrs.put(cw, null, 0, -1, -1, out); } } } libasm4-java-4.1/src/org/objectweb/asm/Frame.java000066400000000000000000001350131207310427500216330ustar00rootroot00000000000000/*** * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.objectweb.asm; /** * Information about the input and output stack map frames of a basic block. * * @author Eric Bruneton */ final class Frame { /* * Frames are computed in a two steps process: during the visit of each * instruction, the state of the frame at the end of current basic block is * updated by simulating the action of the instruction on the previous state * of this so called "output frame". In visitMaxs, a fix point algorithm is * used to compute the "input frame" of each basic block, i.e. the stack map * frame at the beginning of the basic block, starting from the input frame * of the first basic block (which is computed from the method descriptor), * and by using the previously computed output frames to compute the input * state of the other blocks. * * All output and input frames are stored as arrays of integers. Reference * and array types are represented by an index into a type table (which is * not the same as the constant pool of the class, in order to avoid adding * unnecessary constants in the pool - not all computed frames will end up * being stored in the stack map table). This allows very fast type * comparisons. * * Output stack map frames are computed relatively to the input frame of the * basic block, which is not yet known when output frames are computed. It * is therefore necessary to be able to represent abstract types such as * "the type at position x in the input frame locals" or "the type at * position x from the top of the input frame stack" or even "the type at * position x in the input frame, with y more (or less) array dimensions". * This explains the rather complicated type format used in output frames. * * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a * signed number of array dimensions (from -8 to 7). KIND is either BASE, * LOCAL or STACK. BASE is used for types that are not relative to the input * frame. LOCAL is used for types that are relative to the input local * variable types. STACK is used for types that are relative to the input * stack types. VALUE depends on KIND. For LOCAL types, it is an index in * the input local variable types. For STACK types, it is a position * relatively to the top of input frame stack. For BASE types, it is either * one of the constants defined in FrameVisitor, or for OBJECT and * UNINITIALIZED types, a tag and an index in the type table. * * Output frames can contain types of any kind and with a positive or * negative dimension (and even unassigned types, represented by 0 - which * does not correspond to any valid type value). Input frames can only * contain BASE types of positive or null dimension. In all cases the type * table contains only internal type names (array type descriptors are * forbidden - dimensions must be represented through the DIM field). * * The LONG and DOUBLE types are always represented by using two slots (LONG * + TOP or DOUBLE + TOP), for local variable types as well as in the * operand stack. This is necessary to be able to simulate DUPx_y * instructions, whose effect would be dependent on the actual type values * if types were always represented by a single slot in the stack (and this * is not possible, since actual type values are not always known - cf LOCAL * and STACK type kinds). */ /** * Mask to get the dimension of a frame type. This dimension is a signed * integer between -8 and 7. */ static final int DIM = 0xF0000000; /** * Constant to be added to a type to get a type with one more dimension. */ static final int ARRAY_OF = 0x10000000; /** * Constant to be added to a type to get a type with one less dimension. */ static final int ELEMENT_OF = 0xF0000000; /** * Mask to get the kind of a frame type. * * @see #BASE * @see #LOCAL * @see #STACK */ static final int KIND = 0xF000000; /** * Flag used for LOCAL and STACK types. Indicates that if this type happens * to be a long or double type (during the computations of input frames), * then it must be set to TOP because the second word of this value has been * reused to store other data in the basic block. Hence the first word no * longer stores a valid long or double value. */ static final int TOP_IF_LONG_OR_DOUBLE = 0x800000; /** * Mask to get the value of a frame type. */ static final int VALUE = 0x7FFFFF; /** * Mask to get the kind of base types. */ static final int BASE_KIND = 0xFF00000; /** * Mask to get the value of base types. */ static final int BASE_VALUE = 0xFFFFF; /** * Kind of the types that are not relative to an input stack map frame. */ static final int BASE = 0x1000000; /** * Base kind of the base reference types. The BASE_VALUE of such types is an * index into the type table. */ static final int OBJECT = BASE | 0x700000; /** * Base kind of the uninitialized base types. The BASE_VALUE of such types * in an index into the type table (the Item at that index contains both an * instruction offset and an internal class name). */ static final int UNINITIALIZED = BASE | 0x800000; /** * Kind of the types that are relative to the local variable types of an * input stack map frame. The value of such types is a local variable index. */ private static final int LOCAL = 0x2000000; /** * Kind of the the types that are relative to the stack of an input stack * map frame. The value of such types is a position relatively to the top of * this stack. */ private static final int STACK = 0x3000000; /** * The TOP type. This is a BASE type. */ static final int TOP = BASE | 0; /** * The BOOLEAN type. This is a BASE type mainly used for array types. */ static final int BOOLEAN = BASE | 9; /** * The BYTE type. This is a BASE type mainly used for array types. */ static final int BYTE = BASE | 10; /** * The CHAR type. This is a BASE type mainly used for array types. */ static final int CHAR = BASE | 11; /** * The SHORT type. This is a BASE type mainly used for array types. */ static final int SHORT = BASE | 12; /** * The INTEGER type. This is a BASE type. */ static final int INTEGER = BASE | 1; /** * The FLOAT type. This is a BASE type. */ static final int FLOAT = BASE | 2; /** * The DOUBLE type. This is a BASE type. */ static final int DOUBLE = BASE | 3; /** * The LONG type. This is a BASE type. */ static final int LONG = BASE | 4; /** * The NULL type. This is a BASE type. */ static final int NULL = BASE | 5; /** * The UNINITIALIZED_THIS type. This is a BASE type. */ static final int UNINITIALIZED_THIS = BASE | 6; /** * The stack size variation corresponding to each JVM instruction. This * stack variation is equal to the size of the values produced by an * instruction, minus the size of the values consumed by this instruction. */ static final int[] SIZE; /** * Computes the stack size variation corresponding to each JVM instruction. */ static { int i; int[] b = new int[202]; String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD" + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD" + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED" + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE"; for (i = 0; i < b.length; ++i) { b[i] = s.charAt(i) - 'E'; } SIZE = b; // code to generate the above string // // int NA = 0; // not applicable (unused opcode or variable size opcode) // // b = new int[] { // 0, //NOP, // visitInsn // 1, //ACONST_NULL, // - // 1, //ICONST_M1, // - // 1, //ICONST_0, // - // 1, //ICONST_1, // - // 1, //ICONST_2, // - // 1, //ICONST_3, // - // 1, //ICONST_4, // - // 1, //ICONST_5, // - // 2, //LCONST_0, // - // 2, //LCONST_1, // - // 1, //FCONST_0, // - // 1, //FCONST_1, // - // 1, //FCONST_2, // - // 2, //DCONST_0, // - // 2, //DCONST_1, // - // 1, //BIPUSH, // visitIntInsn // 1, //SIPUSH, // - // 1, //LDC, // visitLdcInsn // NA, //LDC_W, // - // NA, //LDC2_W, // - // 1, //ILOAD, // visitVarInsn // 2, //LLOAD, // - // 1, //FLOAD, // - // 2, //DLOAD, // - // 1, //ALOAD, // - // NA, //ILOAD_0, // - // NA, //ILOAD_1, // - // NA, //ILOAD_2, // - // NA, //ILOAD_3, // - // NA, //LLOAD_0, // - // NA, //LLOAD_1, // - // NA, //LLOAD_2, // - // NA, //LLOAD_3, // - // NA, //FLOAD_0, // - // NA, //FLOAD_1, // - // NA, //FLOAD_2, // - // NA, //FLOAD_3, // - // NA, //DLOAD_0, // - // NA, //DLOAD_1, // - // NA, //DLOAD_2, // - // NA, //DLOAD_3, // - // NA, //ALOAD_0, // - // NA, //ALOAD_1, // - // NA, //ALOAD_2, // - // NA, //ALOAD_3, // - // -1, //IALOAD, // visitInsn // 0, //LALOAD, // - // -1, //FALOAD, // - // 0, //DALOAD, // - // -1, //AALOAD, // - // -1, //BALOAD, // - // -1, //CALOAD, // - // -1, //SALOAD, // - // -1, //ISTORE, // visitVarInsn // -2, //LSTORE, // - // -1, //FSTORE, // - // -2, //DSTORE, // - // -1, //ASTORE, // - // NA, //ISTORE_0, // - // NA, //ISTORE_1, // - // NA, //ISTORE_2, // - // NA, //ISTORE_3, // - // NA, //LSTORE_0, // - // NA, //LSTORE_1, // - // NA, //LSTORE_2, // - // NA, //LSTORE_3, // - // NA, //FSTORE_0, // - // NA, //FSTORE_1, // - // NA, //FSTORE_2, // - // NA, //FSTORE_3, // - // NA, //DSTORE_0, // - // NA, //DSTORE_1, // - // NA, //DSTORE_2, // - // NA, //DSTORE_3, // - // NA, //ASTORE_0, // - // NA, //ASTORE_1, // - // NA, //ASTORE_2, // - // NA, //ASTORE_3, // - // -3, //IASTORE, // visitInsn // -4, //LASTORE, // - // -3, //FASTORE, // - // -4, //DASTORE, // - // -3, //AASTORE, // - // -3, //BASTORE, // - // -3, //CASTORE, // - // -3, //SASTORE, // - // -1, //POP, // - // -2, //POP2, // - // 1, //DUP, // - // 1, //DUP_X1, // - // 1, //DUP_X2, // - // 2, //DUP2, // - // 2, //DUP2_X1, // - // 2, //DUP2_X2, // - // 0, //SWAP, // - // -1, //IADD, // - // -2, //LADD, // - // -1, //FADD, // - // -2, //DADD, // - // -1, //ISUB, // - // -2, //LSUB, // - // -1, //FSUB, // - // -2, //DSUB, // - // -1, //IMUL, // - // -2, //LMUL, // - // -1, //FMUL, // - // -2, //DMUL, // - // -1, //IDIV, // - // -2, //LDIV, // - // -1, //FDIV, // - // -2, //DDIV, // - // -1, //IREM, // - // -2, //LREM, // - // -1, //FREM, // - // -2, //DREM, // - // 0, //INEG, // - // 0, //LNEG, // - // 0, //FNEG, // - // 0, //DNEG, // - // -1, //ISHL, // - // -1, //LSHL, // - // -1, //ISHR, // - // -1, //LSHR, // - // -1, //IUSHR, // - // -1, //LUSHR, // - // -1, //IAND, // - // -2, //LAND, // - // -1, //IOR, // - // -2, //LOR, // - // -1, //IXOR, // - // -2, //LXOR, // - // 0, //IINC, // visitIincInsn // 1, //I2L, // visitInsn // 0, //I2F, // - // 1, //I2D, // - // -1, //L2I, // - // -1, //L2F, // - // 0, //L2D, // - // 0, //F2I, // - // 1, //F2L, // - // 1, //F2D, // - // -1, //D2I, // - // 0, //D2L, // - // -1, //D2F, // - // 0, //I2B, // - // 0, //I2C, // - // 0, //I2S, // - // -3, //LCMP, // - // -1, //FCMPL, // - // -1, //FCMPG, // - // -3, //DCMPL, // - // -3, //DCMPG, // - // -1, //IFEQ, // visitJumpInsn // -1, //IFNE, // - // -1, //IFLT, // - // -1, //IFGE, // - // -1, //IFGT, // - // -1, //IFLE, // - // -2, //IF_ICMPEQ, // - // -2, //IF_ICMPNE, // - // -2, //IF_ICMPLT, // - // -2, //IF_ICMPGE, // - // -2, //IF_ICMPGT, // - // -2, //IF_ICMPLE, // - // -2, //IF_ACMPEQ, // - // -2, //IF_ACMPNE, // - // 0, //GOTO, // - // 1, //JSR, // - // 0, //RET, // visitVarInsn // -1, //TABLESWITCH, // visiTableSwitchInsn // -1, //LOOKUPSWITCH, // visitLookupSwitch // -1, //IRETURN, // visitInsn // -2, //LRETURN, // - // -1, //FRETURN, // - // -2, //DRETURN, // - // -1, //ARETURN, // - // 0, //RETURN, // - // NA, //GETSTATIC, // visitFieldInsn // NA, //PUTSTATIC, // - // NA, //GETFIELD, // - // NA, //PUTFIELD, // - // NA, //INVOKEVIRTUAL, // visitMethodInsn // NA, //INVOKESPECIAL, // - // NA, //INVOKESTATIC, // - // NA, //INVOKEINTERFACE, // - // NA, //INVOKEDYNAMIC, // visitInvokeDynamicInsn // 1, //NEW, // visitTypeInsn // 0, //NEWARRAY, // visitIntInsn // 0, //ANEWARRAY, // visitTypeInsn // 0, //ARRAYLENGTH, // visitInsn // NA, //ATHROW, // - // 0, //CHECKCAST, // visitTypeInsn // 0, //INSTANCEOF, // - // -1, //MONITORENTER, // visitInsn // -1, //MONITOREXIT, // - // NA, //WIDE, // NOT VISITED // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn // -1, //IFNULL, // visitJumpInsn // -1, //IFNONNULL, // - // NA, //GOTO_W, // - // NA, //JSR_W, // - // }; // for (i = 0; i < b.length; ++i) { // System.err.print((char)('E' + b[i])); // } // System.err.println(); } /** * The label (i.e. basic block) to which these input and output stack map * frames correspond. */ Label owner; /** * The input stack map frame locals. */ int[] inputLocals; /** * The input stack map frame stack. */ int[] inputStack; /** * The output stack map frame locals. */ private int[] outputLocals; /** * The output stack map frame stack. */ private int[] outputStack; /** * Relative size of the output stack. The exact semantics of this field * depends on the algorithm that is used. * * When only the maximum stack size is computed, this field is the size of * the output stack relatively to the top of the input stack. * * When the stack map frames are completely computed, this field is the * actual number of types in {@link #outputStack}. */ private int outputStackTop; /** * Number of types that are initialized in the basic block. * * @see #initializations */ private int initializationCount; /** * The types that are initialized in the basic block. A constructor * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace * every occurence of this type in the local variables and in the * operand stack. This cannot be done during the first phase of the * algorithm since, during this phase, the local variables and the operand * stack are not completely computed. It is therefore necessary to store the * types on which constructors are invoked in the basic block, in order to * do this replacement during the second phase of the algorithm, where the * frames are fully computed. Note that this array can contain types that * are relative to input locals or to the input stack (see below for the * description of the algorithm). */ private int[] initializations; /** * Returns the output frame local variable type at the given index. * * @param local * the index of the local that must be returned. * @return the output frame local variable type at the given index. */ private int get(final int local) { if (outputLocals == null || local >= outputLocals.length) { // this local has never been assigned in this basic block, // so it is still equal to its value in the input frame return LOCAL | local; } else { int type = outputLocals[local]; if (type == 0) { // this local has never been assigned in this basic block, // so it is still equal to its value in the input frame type = outputLocals[local] = LOCAL | local; } return type; } } /** * Sets the output frame local variable type at the given index. * * @param local * the index of the local that must be set. * @param type * the value of the local that must be set. */ private void set(final int local, final int type) { // creates and/or resizes the output local variables array if necessary if (outputLocals == null) { outputLocals = new int[10]; } int n = outputLocals.length; if (local >= n) { int[] t = new int[Math.max(local + 1, 2 * n)]; System.arraycopy(outputLocals, 0, t, 0, n); outputLocals = t; } // sets the local variable outputLocals[local] = type; } /** * Pushes a new type onto the output frame stack. * * @param type * the type that must be pushed. */ private void push(final int type) { // creates and/or resizes the output stack array if necessary if (outputStack == null) { outputStack = new int[10]; } int n = outputStack.length; if (outputStackTop >= n) { int[] t = new int[Math.max(outputStackTop + 1, 2 * n)]; System.arraycopy(outputStack, 0, t, 0, n); outputStack = t; } // pushes the type on the output stack outputStack[outputStackTop++] = type; // updates the maximun height reached by the output stack, if needed int top = owner.inputStackTop + outputStackTop; if (top > owner.outputStackMax) { owner.outputStackMax = top; } } /** * Pushes a new type onto the output frame stack. * * @param cw * the ClassWriter to which this label belongs. * @param desc * the descriptor of the type to be pushed. Can also be a method * descriptor (in this case this method pushes its return type * onto the output frame stack). */ private void push(final ClassWriter cw, final String desc) { int type = type(cw, desc); if (type != 0) { push(type); if (type == LONG || type == DOUBLE) { push(TOP); } } } /** * Returns the int encoding of the given type. * * @param cw * the ClassWriter to which this label belongs. * @param desc * a type descriptor. * @return the int encoding of the given type. */ private static int type(final ClassWriter cw, final String desc) { String t; int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0; switch (desc.charAt(index)) { case 'V': return 0; case 'Z': case 'C': case 'B': case 'S': case 'I': return INTEGER; case 'F': return FLOAT; case 'J': return LONG; case 'D': return DOUBLE; case 'L': // stores the internal name, not the descriptor! t = desc.substring(index + 1, desc.length() - 1); return OBJECT | cw.addType(t); // case '[': default: // extracts the dimensions and the element type int data; int dims = index + 1; while (desc.charAt(dims) == '[') { ++dims; } switch (desc.charAt(dims)) { case 'Z': data = BOOLEAN; break; case 'C': data = CHAR; break; case 'B': data = BYTE; break; case 'S': data = SHORT; break; case 'I': data = INTEGER; break; case 'F': data = FLOAT; break; case 'J': data = LONG; break; case 'D': data = DOUBLE; break; // case 'L': default: // stores the internal name, not the descriptor t = desc.substring(dims + 1, desc.length() - 1); data = OBJECT | cw.addType(t); } return (dims - index) << 28 | data; } } /** * Pops a type from the output frame stack and returns its value. * * @return the type that has been popped from the output frame stack. */ private int pop() { if (outputStackTop > 0) { return outputStack[--outputStackTop]; } else { // if the output frame stack is empty, pops from the input stack return STACK | -(--owner.inputStackTop); } } /** * Pops the given number of types from the output frame stack. * * @param elements * the number of types that must be popped. */ private void pop(final int elements) { if (outputStackTop >= elements) { outputStackTop -= elements; } else { // if the number of elements to be popped is greater than the number // of elements in the output stack, clear it, and pops the remaining // elements from the input stack. owner.inputStackTop -= elements - outputStackTop; outputStackTop = 0; } } /** * Pops a type from the output frame stack. * * @param desc * the descriptor of the type to be popped. Can also be a method * descriptor (in this case this method pops the types * corresponding to the method arguments). */ private void pop(final String desc) { char c = desc.charAt(0); if (c == '(') { pop((Type.getArgumentsAndReturnSizes(desc) >> 2) - 1); } else if (c == 'J' || c == 'D') { pop(2); } else { pop(1); } } /** * Adds a new type to the list of types on which a constructor is invoked in * the basic block. * * @param var * a type on a which a constructor is invoked. */ private void init(final int var) { // creates and/or resizes the initializations array if necessary if (initializations == null) { initializations = new int[2]; } int n = initializations.length; if (initializationCount >= n) { int[] t = new int[Math.max(initializationCount + 1, 2 * n)]; System.arraycopy(initializations, 0, t, 0, n); initializations = t; } // stores the type to be initialized initializations[initializationCount++] = var; } /** * Replaces the given type with the appropriate type if it is one of the * types on which a constructor is invoked in the basic block. * * @param cw * the ClassWriter to which this label belongs. * @param t * a type * @return t or, if t is one of the types on which a constructor is invoked * in the basic block, the type corresponding to this constructor. */ private int init(final ClassWriter cw, final int t) { int s; if (t == UNINITIALIZED_THIS) { s = OBJECT | cw.addType(cw.thisName); } else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) { String type = cw.typeTable[t & BASE_VALUE].strVal1; s = OBJECT | cw.addType(type); } else { return t; } for (int j = 0; j < initializationCount; ++j) { int u = initializations[j]; int dim = u & DIM; int kind = u & KIND; if (kind == LOCAL) { u = dim + inputLocals[u & VALUE]; } else if (kind == STACK) { u = dim + inputStack[inputStack.length - (u & VALUE)]; } if (t == u) { return s; } } return t; } /** * Initializes the input frame of the first basic block from the method * descriptor. * * @param cw * the ClassWriter to which this label belongs. * @param access * the access flags of the method to which this label belongs. * @param args * the formal parameter types of this method. * @param maxLocals * the maximum number of local variables of this method. */ void initInputFrame(final ClassWriter cw, final int access, final Type[] args, final int maxLocals) { inputLocals = new int[maxLocals]; inputStack = new int[0]; int i = 0; if ((access & Opcodes.ACC_STATIC) == 0) { if ((access & MethodWriter.ACC_CONSTRUCTOR) == 0) { inputLocals[i++] = OBJECT | cw.addType(cw.thisName); } else { inputLocals[i++] = UNINITIALIZED_THIS; } } for (int j = 0; j < args.length; ++j) { int t = type(cw, args[j].getDescriptor()); inputLocals[i++] = t; if (t == LONG || t == DOUBLE) { inputLocals[i++] = TOP; } } while (i < maxLocals) { inputLocals[i++] = TOP; } } /** * Simulates the action of the given instruction on the output stack frame. * * @param opcode * the opcode of the instruction. * @param arg * the operand of the instruction, if any. * @param cw * the class writer to which this label belongs. * @param item * the operand of the instructions, if any. */ void execute(final int opcode, final int arg, final ClassWriter cw, final Item item) { int t1, t2, t3, t4; switch (opcode) { case Opcodes.NOP: case Opcodes.INEG: case Opcodes.LNEG: case Opcodes.FNEG: case Opcodes.DNEG: case Opcodes.I2B: case Opcodes.I2C: case Opcodes.I2S: case Opcodes.GOTO: case Opcodes.RETURN: break; case Opcodes.ACONST_NULL: push(NULL); break; case Opcodes.ICONST_M1: case Opcodes.ICONST_0: case Opcodes.ICONST_1: case Opcodes.ICONST_2: case Opcodes.ICONST_3: case Opcodes.ICONST_4: case Opcodes.ICONST_5: case Opcodes.BIPUSH: case Opcodes.SIPUSH: case Opcodes.ILOAD: push(INTEGER); break; case Opcodes.LCONST_0: case Opcodes.LCONST_1: case Opcodes.LLOAD: push(LONG); push(TOP); break; case Opcodes.FCONST_0: case Opcodes.FCONST_1: case Opcodes.FCONST_2: case Opcodes.FLOAD: push(FLOAT); break; case Opcodes.DCONST_0: case Opcodes.DCONST_1: case Opcodes.DLOAD: push(DOUBLE); push(TOP); break; case Opcodes.LDC: switch (item.type) { case ClassWriter.INT: push(INTEGER); break; case ClassWriter.LONG: push(LONG); push(TOP); break; case ClassWriter.FLOAT: push(FLOAT); break; case ClassWriter.DOUBLE: push(DOUBLE); push(TOP); break; case ClassWriter.CLASS: push(OBJECT | cw.addType("java/lang/Class")); break; case ClassWriter.STR: push(OBJECT | cw.addType("java/lang/String")); break; case ClassWriter.MTYPE: push(OBJECT | cw.addType("java/lang/invoke/MethodType")); break; // case ClassWriter.HANDLE_BASE + [1..9]: default: push(OBJECT | cw.addType("java/lang/invoke/MethodHandle")); } break; case Opcodes.ALOAD: push(get(arg)); break; case Opcodes.IALOAD: case Opcodes.BALOAD: case Opcodes.CALOAD: case Opcodes.SALOAD: pop(2); push(INTEGER); break; case Opcodes.LALOAD: case Opcodes.D2L: pop(2); push(LONG); push(TOP); break; case Opcodes.FALOAD: pop(2); push(FLOAT); break; case Opcodes.DALOAD: case Opcodes.L2D: pop(2); push(DOUBLE); push(TOP); break; case Opcodes.AALOAD: pop(1); t1 = pop(); push(ELEMENT_OF + t1); break; case Opcodes.ISTORE: case Opcodes.FSTORE: case Opcodes.ASTORE: t1 = pop(); set(arg, t1); if (arg > 0) { t2 = get(arg - 1); // if t2 is of kind STACK or LOCAL we cannot know its size! if (t2 == LONG || t2 == DOUBLE) { set(arg - 1, TOP); } else if ((t2 & KIND) != BASE) { set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE); } } break; case Opcodes.LSTORE: case Opcodes.DSTORE: pop(1); t1 = pop(); set(arg, t1); set(arg + 1, TOP); if (arg > 0) { t2 = get(arg - 1); // if t2 is of kind STACK or LOCAL we cannot know its size! if (t2 == LONG || t2 == DOUBLE) { set(arg - 1, TOP); } else if ((t2 & KIND) != BASE) { set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE); } } break; case Opcodes.IASTORE: case Opcodes.BASTORE: case Opcodes.CASTORE: case Opcodes.SASTORE: case Opcodes.FASTORE: case Opcodes.AASTORE: pop(3); break; case Opcodes.LASTORE: case Opcodes.DASTORE: pop(4); break; case Opcodes.POP: case Opcodes.IFEQ: case Opcodes.IFNE: case Opcodes.IFLT: case Opcodes.IFGE: case Opcodes.IFGT: case Opcodes.IFLE: case Opcodes.IRETURN: case Opcodes.FRETURN: case Opcodes.ARETURN: case Opcodes.TABLESWITCH: case Opcodes.LOOKUPSWITCH: case Opcodes.ATHROW: case Opcodes.MONITORENTER: case Opcodes.MONITOREXIT: case Opcodes.IFNULL: case Opcodes.IFNONNULL: pop(1); break; case Opcodes.POP2: case Opcodes.IF_ICMPEQ: case Opcodes.IF_ICMPNE: case Opcodes.IF_ICMPLT: case Opcodes.IF_ICMPGE: case Opcodes.IF_ICMPGT: case Opcodes.IF_ICMPLE: case Opcodes.IF_ACMPEQ: case Opcodes.IF_ACMPNE: case Opcodes.LRETURN: case Opcodes.DRETURN: pop(2); break; case Opcodes.DUP: t1 = pop(); push(t1); push(t1); break; case Opcodes.DUP_X1: t1 = pop(); t2 = pop(); push(t1); push(t2); push(t1); break; case Opcodes.DUP_X2: t1 = pop(); t2 = pop(); t3 = pop(); push(t1); push(t3); push(t2); push(t1); break; case Opcodes.DUP2: t1 = pop(); t2 = pop(); push(t2); push(t1); push(t2); push(t1); break; case Opcodes.DUP2_X1: t1 = pop(); t2 = pop(); t3 = pop(); push(t2); push(t1); push(t3); push(t2); push(t1); break; case Opcodes.DUP2_X2: t1 = pop(); t2 = pop(); t3 = pop(); t4 = pop(); push(t2); push(t1); push(t4); push(t3); push(t2); push(t1); break; case Opcodes.SWAP: t1 = pop(); t2 = pop(); push(t1); push(t2); break; case Opcodes.IADD: case Opcodes.ISUB: case Opcodes.IMUL: case Opcodes.IDIV: case Opcodes.IREM: case Opcodes.IAND: case Opcodes.IOR: case Opcodes.IXOR: case Opcodes.ISHL: case Opcodes.ISHR: case Opcodes.IUSHR: case Opcodes.L2I: case Opcodes.D2I: case Opcodes.FCMPL: case Opcodes.FCMPG: pop(2); push(INTEGER); break; case Opcodes.LADD: case Opcodes.LSUB: case Opcodes.LMUL: case Opcodes.LDIV: case Opcodes.LREM: case Opcodes.LAND: case Opcodes.LOR: case Opcodes.LXOR: pop(4); push(LONG); push(TOP); break; case Opcodes.FADD: case Opcodes.FSUB: case Opcodes.FMUL: case Opcodes.FDIV: case Opcodes.FREM: case Opcodes.L2F: case Opcodes.D2F: pop(2); push(FLOAT); break; case Opcodes.DADD: case Opcodes.DSUB: case Opcodes.DMUL: case Opcodes.DDIV: case Opcodes.DREM: pop(4); push(DOUBLE); push(TOP); break; case Opcodes.LSHL: case Opcodes.LSHR: case Opcodes.LUSHR: pop(3); push(LONG); push(TOP); break; case Opcodes.IINC: set(arg, INTEGER); break; case Opcodes.I2L: case Opcodes.F2L: pop(1); push(LONG); push(TOP); break; case Opcodes.I2F: pop(1); push(FLOAT); break; case Opcodes.I2D: case Opcodes.F2D: pop(1); push(DOUBLE); push(TOP); break; case Opcodes.F2I: case Opcodes.ARRAYLENGTH: case Opcodes.INSTANCEOF: pop(1); push(INTEGER); break; case Opcodes.LCMP: case Opcodes.DCMPL: case Opcodes.DCMPG: pop(4); push(INTEGER); break; case Opcodes.JSR: case Opcodes.RET: throw new RuntimeException( "JSR/RET are not supported with computeFrames option"); case Opcodes.GETSTATIC: push(cw, item.strVal3); break; case Opcodes.PUTSTATIC: pop(item.strVal3); break; case Opcodes.GETFIELD: pop(1); push(cw, item.strVal3); break; case Opcodes.PUTFIELD: pop(item.strVal3); pop(); break; case Opcodes.INVOKEVIRTUAL: case Opcodes.INVOKESPECIAL: case Opcodes.INVOKESTATIC: case Opcodes.INVOKEINTERFACE: pop(item.strVal3); if (opcode != Opcodes.INVOKESTATIC) { t1 = pop(); if (opcode == Opcodes.INVOKESPECIAL && item.strVal2.charAt(0) == '<') { init(t1); } } push(cw, item.strVal3); break; case Opcodes.INVOKEDYNAMIC: pop(item.strVal2); push(cw, item.strVal2); break; case Opcodes.NEW: push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg)); break; case Opcodes.NEWARRAY: pop(); switch (arg) { case Opcodes.T_BOOLEAN: push(ARRAY_OF | BOOLEAN); break; case Opcodes.T_CHAR: push(ARRAY_OF | CHAR); break; case Opcodes.T_BYTE: push(ARRAY_OF | BYTE); break; case Opcodes.T_SHORT: push(ARRAY_OF | SHORT); break; case Opcodes.T_INT: push(ARRAY_OF | INTEGER); break; case Opcodes.T_FLOAT: push(ARRAY_OF | FLOAT); break; case Opcodes.T_DOUBLE: push(ARRAY_OF | DOUBLE); break; // case Opcodes.T_LONG: default: push(ARRAY_OF | LONG); break; } break; case Opcodes.ANEWARRAY: String s = item.strVal1; pop(); if (s.charAt(0) == '[') { push(cw, '[' + s); } else { push(ARRAY_OF | OBJECT | cw.addType(s)); } break; case Opcodes.CHECKCAST: s = item.strVal1; pop(); if (s.charAt(0) == '[') { push(cw, s); } else { push(OBJECT | cw.addType(s)); } break; // case Opcodes.MULTIANEWARRAY: default: pop(arg); push(cw, item.strVal1); break; } } /** * Merges the input frame of the given basic block with the input and output * frames of this basic block. Returns true if the input frame of * the given label has been changed by this operation. * * @param cw * the ClassWriter to which this label belongs. * @param frame * the basic block whose input frame must be updated. * @param edge * the kind of the {@link Edge} between this label and 'label'. * See {@link Edge#info}. * @return true if the input frame of the given label has been * changed by this operation. */ boolean merge(final ClassWriter cw, final Frame frame, final int edge) { boolean changed = false; int i, s, dim, kind, t; int nLocal = inputLocals.length; int nStack = inputStack.length; if (frame.inputLocals == null) { frame.inputLocals = new int[nLocal]; changed = true; } for (i = 0; i < nLocal; ++i) { if (outputLocals != null && i < outputLocals.length) { s = outputLocals[i]; if (s == 0) { t = inputLocals[i]; } else { dim = s & DIM; kind = s & KIND; if (kind == BASE) { t = s; } else { if (kind == LOCAL) { t = dim + inputLocals[s & VALUE]; } else { t = dim + inputStack[nStack - (s & VALUE)]; } if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 && (t == LONG || t == DOUBLE)) { t = TOP; } } } } else { t = inputLocals[i]; } if (initializations != null) { t = init(cw, t); } changed |= merge(cw, t, frame.inputLocals, i); } if (edge > 0) { for (i = 0; i < nLocal; ++i) { t = inputLocals[i]; changed |= merge(cw, t, frame.inputLocals, i); } if (frame.inputStack == null) { frame.inputStack = new int[1]; changed = true; } changed |= merge(cw, edge, frame.inputStack, 0); return changed; } int nInputStack = inputStack.length + owner.inputStackTop; if (frame.inputStack == null) { frame.inputStack = new int[nInputStack + outputStackTop]; changed = true; } for (i = 0; i < nInputStack; ++i) { t = inputStack[i]; if (initializations != null) { t = init(cw, t); } changed |= merge(cw, t, frame.inputStack, i); } for (i = 0; i < outputStackTop; ++i) { s = outputStack[i]; dim = s & DIM; kind = s & KIND; if (kind == BASE) { t = s; } else { if (kind == LOCAL) { t = dim + inputLocals[s & VALUE]; } else { t = dim + inputStack[nStack - (s & VALUE)]; } if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 && (t == LONG || t == DOUBLE)) { t = TOP; } } if (initializations != null) { t = init(cw, t); } changed |= merge(cw, t, frame.inputStack, nInputStack + i); } return changed; } /** * Merges the type at the given index in the given type array with the given * type. Returns true if the type array has been modified by this * operation. * * @param cw * the ClassWriter to which this label belongs. * @param t * the type with which the type array element must be merged. * @param types * an array of types. * @param index * the index of the type that must be merged in 'types'. * @return true if the type array has been modified by this * operation. */ private static boolean merge(final ClassWriter cw, int t, final int[] types, final int index) { int u = types[index]; if (u == t) { // if the types are equal, merge(u,t)=u, so there is no change return false; } if ((t & ~DIM) == NULL) { if (u == NULL) { return false; } t = NULL; } if (u == 0) { // if types[index] has never been assigned, merge(u,t)=t types[index] = t; return true; } int v; if ((u & BASE_KIND) == OBJECT || (u & DIM) != 0) { // if u is a reference type of any dimension if (t == NULL) { // if t is the NULL type, merge(u,t)=u, so there is no change return false; } else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) { if ((u & BASE_KIND) == OBJECT) { // if t is also a reference type, and if u and t have the // same dimension merge(u,t) = dim(t) | common parent of the // element types of u and t v = (t & DIM) | OBJECT | cw.getMergedType(t & BASE_VALUE, u & BASE_VALUE); } else { // if u and t are array types, but not with the same element // type, merge(u,t)=java/lang/Object v = OBJECT | cw.addType("java/lang/Object"); } } else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) { // if t is any other reference or array type, // merge(u,t)=java/lang/Object v = OBJECT | cw.addType("java/lang/Object"); } else { // if t is any other type, merge(u,t)=TOP v = TOP; } } else if (u == NULL) { // if u is the NULL type, merge(u,t)=t, // or TOP if t is not a reference type v = (t & BASE_KIND) == OBJECT || (t & DIM) != 0 ? t : TOP; } else { // if u is any other type, merge(u,t)=TOP whatever t v = TOP; } if (u != v) { types[index] = v; return true; } return false; } } libasm4-java-4.1/src/org/objectweb/asm/Handle.java000066400000000000000000000132131207310427500217710ustar00rootroot00000000000000/*** * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.objectweb.asm; /** * A reference to a field or a method. * * @author Remi Forax * @author Eric Bruneton */ public final class Handle { /** * The kind of field or method designated by this Handle. Should be * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, * {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or * {@link Opcodes#H_INVOKEINTERFACE}. */ final int tag; /** * The internal name of the field or method designed by this handle. */ final String owner; /** * The name of the field or method designated by this handle. */ final String name; /** * The descriptor of the field or method designated by this handle. */ final String desc; /** * Constructs a new field or method handle. * * @param tag * the kind of field or method designated by this Handle. Must be * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, * {@link Opcodes#H_INVOKEVIRTUAL}, * {@link Opcodes#H_INVOKESTATIC}, * {@link Opcodes#H_INVOKESPECIAL}, * {@link Opcodes#H_NEWINVOKESPECIAL} or * {@link Opcodes#H_INVOKEINTERFACE}. * @param owner * the internal name of the field or method designed by this * handle. * @param name * the name of the field or method designated by this handle. * @param desc * the descriptor of the field or method designated by this * handle. */ public Handle(int tag, String owner, String name, String desc) { this.tag = tag; this.owner = owner; this.name = name; this.desc = desc; } /** * Returns the kind of field or method designated by this handle. * * @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, * {@link Opcodes#H_INVOKESPECIAL}, * {@link Opcodes#H_NEWINVOKESPECIAL} or * {@link Opcodes#H_INVOKEINTERFACE}. */ public int getTag() { return tag; } /** * Returns the internal name of the field or method designed by this handle. * * @return the internal name of the field or method designed by this handle. */ public String getOwner() { return owner; } /** * Returns the name of the field or method designated by this handle. * * @return the name of the field or method designated by this handle. */ public String getName() { return name; } /** * Returns the descriptor of the field or method designated by this handle. * * @return the descriptor of the field or method designated by this handle. */ public String getDesc() { return desc; } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof Handle)) { return false; } Handle h = (Handle) obj; return tag == h.tag && owner.equals(h.owner) && name.equals(h.name) && desc.equals(h.desc); } @Override public int hashCode() { return tag + owner.hashCode() * name.hashCode() * desc.hashCode(); } /** * Returns the textual representation of this handle. The textual * representation is: * *
     * owner '.' name desc ' ' '(' tag ')'
     * 
* * . As this format is unambiguous, it can be parsed if necessary. */ @Override public String toString() { return owner + '.' + name + desc + " (" + tag + ')'; } } libasm4-java-4.1/src/org/objectweb/asm/Handler.java000066400000000000000000000101531207310427500221530ustar00rootroot00000000000000/*** * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.objectweb.asm; /** * Information about an exception handler block. * * @author Eric Bruneton */ class Handler { /** * Beginning of the exception handler's scope (inclusive). */ Label start; /** * End of the exception handler's scope (exclusive). */ Label end; /** * Beginning of the exception handler's code. */ Label handler; /** * Internal name of the type of exceptions handled by this handler, or * null to catch any exceptions. */ String desc; /** * Constant pool index of the internal name of the type of exceptions * handled by this handler, or 0 to catch any exceptions. */ int type; /** * Next exception handler block info. */ Handler next; /** * Removes the range between start and end from the given exception * handlers. * * @param h * an exception handler list. * @param start * the start of the range to be removed. * @param end * the end of the range to be removed. Maybe null. * @return the exception handler list with the start-end range removed. */ static Handler remove(Handler h, Label start, Label end) { if (h == null) { return null; } else { h.next = remove(h.next, start, end); } int hstart = h.start.position; int hend = h.end.position; int s = start.position; int e = end == null ? Integer.MAX_VALUE : end.position; // if [hstart,hend[ and [s,e[ intervals intersect... if (s < hend && e > hstart) { if (s <= hstart) { if (e >= hend) { // [hstart,hend[ fully included in [s,e[, h removed h = h.next; } else { // [hstart,hend[ minus [s,e[ = [e,hend[ h.start = end; } } else if (e >= hend) { // [hstart,hend[ minus [s,e[ = [hstart,s[ h.end = start; } else { // [hstart,hend[ minus [s,e[ = [hstart,s[ + [e,hend[ Handler g = new Handler(); g.start = end; g.end = h.end; g.handler = h.handler; g.desc = h.desc; g.type = h.type; g.next = h.next; h.end = start; h.next = g; } } return h; } } libasm4-java-4.1/src/org/objectweb/asm/Item.java000066400000000000000000000237401207310427500215020ustar00rootroot00000000000000/*** * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.objectweb.asm; /** * A constant pool item. Constant pool items can be created with the 'newXXX' * methods in the {@link ClassWriter} class. * * @author Eric Bruneton */ final class Item { /** * Index of this item in the constant pool. */ int index; /** * Type of this constant pool item. A single class is used to represent all * constant pool item types, in order to minimize the bytecode size of this * package. The value of this field is one of {@link ClassWriter#INT}, * {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT}, * {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8}, * {@link ClassWriter#STR}, {@link ClassWriter#CLASS}, * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD}, * {@link ClassWriter#METH}, {@link ClassWriter#IMETH}, * {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}. * * MethodHandle constant 9 variations are stored using a range of 9 values * from {@link ClassWriter#HANDLE_BASE} + 1 to * {@link ClassWriter#HANDLE_BASE} + 9. * * Special Item types are used for Items that are stored in the ClassWriter * {@link ClassWriter#typeTable}, instead of the constant pool, in order to * avoid clashes with normal constant pool items in the ClassWriter constant * pool's hash table. These special item types are * {@link ClassWriter#TYPE_NORMAL}, {@link ClassWriter#TYPE_UNINIT} and * {@link ClassWriter#TYPE_MERGED}. */ int type; /** * Value of this item, for an integer item. */ int intVal; /** * Value of this item, for a long item. */ long longVal; /** * First part of the value of this item, for items that do not hold a * primitive value. */ String strVal1; /** * Second part of the value of this item, for items that do not hold a * primitive value. */ String strVal2; /** * Third part of the value of this item, for items that do not hold a * primitive value. */ String strVal3; /** * The hash code value of this constant pool item. */ int hashCode; /** * Link to another constant pool item, used for collision lists in the * constant pool's hash table. */ Item next; /** * Constructs an uninitialized {@link Item}. */ Item() { } /** * Constructs an uninitialized {@link Item} for constant pool element at * given position. * * @param index * index of the item to be constructed. */ Item(final int index) { this.index = index; } /** * Constructs a copy of the given item. * * @param index * index of the item to be constructed. * @param i * the item that must be copied into the item to be constructed. */ Item(final int index, final Item i) { this.index = index; type = i.type; intVal = i.intVal; longVal = i.longVal; strVal1 = i.strVal1; strVal2 = i.strVal2; strVal3 = i.strVal3; hashCode = i.hashCode; } /** * Sets this item to an integer item. * * @param intVal * the value of this item. */ void set(final int intVal) { this.type = ClassWriter.INT; this.intVal = intVal; this.hashCode = 0x7FFFFFFF & (type + intVal); } /** * Sets this item to a long item. * * @param longVal * the value of this item. */ void set(final long longVal) { this.type = ClassWriter.LONG; this.longVal = longVal; this.hashCode = 0x7FFFFFFF & (type + (int) longVal); } /** * Sets this item to a float item. * * @param floatVal * the value of this item. */ void set(final float floatVal) { this.type = ClassWriter.FLOAT; this.intVal = Float.floatToRawIntBits(floatVal); this.hashCode = 0x7FFFFFFF & (type + (int) floatVal); } /** * Sets this item to a double item. * * @param doubleVal * the value of this item. */ void set(final double doubleVal) { this.type = ClassWriter.DOUBLE; this.longVal = Double.doubleToRawLongBits(doubleVal); this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal); } /** * Sets this item to an item that do not hold a primitive value. * * @param type * the type of this item. * @param strVal1 * first part of the value of this item. * @param strVal2 * second part of the value of this item. * @param strVal3 * third part of the value of this item. */ void set(final int type, final String strVal1, final String strVal2, final String strVal3) { this.type = type; this.strVal1 = strVal1; this.strVal2 = strVal2; this.strVal3 = strVal3; switch (type) { case ClassWriter.UTF8: case ClassWriter.STR: case ClassWriter.CLASS: case ClassWriter.MTYPE: case ClassWriter.TYPE_NORMAL: hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()); return; case ClassWriter.NAME_TYPE: { hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() * strVal2.hashCode()); return; } // ClassWriter.FIELD: // ClassWriter.METH: // ClassWriter.IMETH: // ClassWriter.HANDLE_BASE + 1..9 default: hashCode = 0x7FFFFFFF & (type + strVal1.hashCode() * strVal2.hashCode() * strVal3.hashCode()); } } /** * Sets the item to an InvokeDynamic item. * * @param name * invokedynamic's name. * @param desc * invokedynamic's desc. * @param bsmIndex * zero based index into the class attribute BootrapMethods. */ void set(String name, String desc, int bsmIndex) { this.type = ClassWriter.INDY; this.longVal = bsmIndex; this.strVal1 = name; this.strVal2 = desc; this.hashCode = 0x7FFFFFFF & (ClassWriter.INDY + bsmIndex * strVal1.hashCode() * strVal2.hashCode()); } /** * Sets the item to a BootstrapMethod item. * * @param position * position in byte in the class attribute BootrapMethods. * @param hashCode * hashcode of the item. This hashcode is processed from the * hashcode of the bootstrap method and the hashcode of all * bootstrap arguments. */ void set(int position, int hashCode) { this.type = ClassWriter.BSM; this.intVal = position; this.hashCode = hashCode; } /** * Indicates if the given item is equal to this one. This method assumes * that the two items have the same {@link #type}. * * @param i * the item to be compared to this one. Both items must have the * same {@link #type}. * @return true if the given item if equal to this one, * false otherwise. */ boolean isEqualTo(final Item i) { switch (type) { case ClassWriter.UTF8: case ClassWriter.STR: case ClassWriter.CLASS: case ClassWriter.MTYPE: case ClassWriter.TYPE_NORMAL: return i.strVal1.equals(strVal1); case ClassWriter.TYPE_MERGED: case ClassWriter.LONG: case ClassWriter.DOUBLE: return i.longVal == longVal; case ClassWriter.INT: case ClassWriter.FLOAT: return i.intVal == intVal; case ClassWriter.TYPE_UNINIT: return i.intVal == intVal && i.strVal1.equals(strVal1); case ClassWriter.NAME_TYPE: return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2); case ClassWriter.INDY: { return i.longVal == longVal && i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2); } // case ClassWriter.FIELD: // case ClassWriter.METH: // case ClassWriter.IMETH: // case ClassWriter.HANDLE_BASE + 1..9 default: return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2) && i.strVal3.equals(strVal3); } } } libasm4-java-4.1/src/org/objectweb/asm/Label.java000066400000000000000000000535201207310427500216220ustar00rootroot00000000000000/*** * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.objectweb.asm; /** * A label represents a position in the bytecode of a method. Labels are used * for jump, goto, and switch instructions, and for try catch blocks. A label * designates the instruction that is just after. Note however that there * can be other elements between a label and the instruction it designates (such * as other labels, stack map frames, line numbers, etc.). * * @author Eric Bruneton */ public class Label { /** * Indicates if this label is only used for debug attributes. Such a label * is not the start of a basic block, the target of a jump instruction, or * an exception handler. It can be safely ignored in control flow graph * analysis algorithms (for optimization purposes). */ static final int DEBUG = 1; /** * Indicates if the position of this label is known. */ static final int RESOLVED = 2; /** * Indicates if this label has been updated, after instruction resizing. */ static final int RESIZED = 4; /** * Indicates if this basic block has been pushed in the basic block stack. * See {@link MethodWriter#visitMaxs visitMaxs}. */ static final int PUSHED = 8; /** * Indicates if this label is the target of a jump instruction, or the start * of an exception handler. */ static final int TARGET = 16; /** * Indicates if a stack map frame must be stored for this label. */ static final int STORE = 32; /** * Indicates if this label corresponds to a reachable basic block. */ static final int REACHABLE = 64; /** * Indicates if this basic block ends with a JSR instruction. */ static final int JSR = 128; /** * Indicates if this basic block ends with a RET instruction. */ static final int RET = 256; /** * Indicates if this basic block is the start of a subroutine. */ static final int SUBROUTINE = 512; /** * Indicates if this subroutine basic block has been visited by a * visitSubroutine(null, ...) call. */ static final int VISITED = 1024; /** * Indicates if this subroutine basic block has been visited by a * visitSubroutine(!null, ...) call. */ static final int VISITED2 = 2048; /** * Field used to associate user information to a label. Warning: this field * is used by the ASM tree package. In order to use it with the ASM tree * package you must override the * {@link org.objectweb.asm.tree.MethodNode#getLabelNode} method. */ public Object info; /** * Flags that indicate the status of this label. * * @see #DEBUG * @see #RESOLVED * @see #RESIZED * @see #PUSHED * @see #TARGET * @see #STORE * @see #REACHABLE * @see #JSR * @see #RET */ int status; /** * The line number corresponding to this label, if known. */ int line; /** * The position of this label in the code, if known. */ int position; /** * Number of forward references to this label, times two. */ private int referenceCount; /** * Informations about forward references. Each forward reference is * described by two consecutive integers in this array: the first one is the * position of the first byte of the bytecode instruction that contains the * forward reference, while the second is the position of the first byte of * the forward reference itself. In fact the sign of the first integer * indicates if this reference uses 2 or 4 bytes, and its absolute value * gives the position of the bytecode instruction. This array is also used * as a bitset to store the subroutines to which a basic block belongs. This * information is needed in {@linked MethodWriter#visitMaxs}, after all * forward references have been resolved. Hence the same array can be used * for both purposes without problems. */ private int[] srcAndRefPositions; // ------------------------------------------------------------------------ /* * Fields for the control flow and data flow graph analysis algorithms (used * to compute the maximum stack size or the stack map frames). A control * flow graph contains one node per "basic block", and one edge per "jump" * from one basic block to another. Each node (i.e., each basic block) is * represented by the Label object that corresponds to the first instruction * of this basic block. Each node also stores the list of its successors in * the graph, as a linked list of Edge objects. * * The control flow analysis algorithms used to compute the maximum stack * size or the stack map frames are similar and use two steps. The first * step, during the visit of each instruction, builds information about the * state of the local variables and the operand stack at the end of each * basic block, called the "output frame", relatively to the frame * state at the beginning of the basic block, which is called the "input * frame", and which is unknown during this step. The second step, in * {@link MethodWriter#visitMaxs}, is a fix point algorithm that computes * information about the input frame of each basic block, from the input * state of the first basic block (known from the method signature), and by * the using the previously computed relative output frames. * * The algorithm used to compute the maximum stack size only computes the * relative output and absolute input stack heights, while the algorithm * used to compute stack map frames computes relative output frames and * absolute input frames. */ /** * Start of the output stack relatively to the input stack. The exact * semantics of this field depends on the algorithm that is used. * * When only the maximum stack size is computed, this field is the number of * elements in the input stack. * * When the stack map frames are completely computed, this field is the * offset of the first output stack element relatively to the top of the * input stack. This offset is always negative or null. A null offset means * that the output stack must be appended to the input stack. A -n offset * means that the first n output stack elements must replace the top n input * stack elements, and that the other elements must be appended to the input * stack. */ int inputStackTop; /** * Maximum height reached by the output stack, relatively to the top of the * input stack. This maximum is always positive or null. */ int outputStackMax; /** * Information about the input and output stack map frames of this basic * block. This field is only used when {@link ClassWriter#COMPUTE_FRAMES} * option is used. */ Frame frame; /** * The successor of this label, in the order they are visited. This linked * list does not include labels used for debug info only. If * {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it * does not contain successive labels that denote the same bytecode position * (in this case only the first label appears in this list). */ Label successor; /** * The successors of this node in the control flow graph. These successors * are stored in a linked list of {@link Edge Edge} objects, linked to each * other by their {@link Edge#next} field. */ Edge successors; /** * The next basic block in the basic block stack. This stack is used in the * main loop of the fix point algorithm used in the second step of the * control flow analysis algorithms. It is also used in * {@link #visitSubroutine} to avoid using a recursive method. * * @see MethodWriter#visitMaxs */ Label next; // ------------------------------------------------------------------------ // Constructor // ------------------------------------------------------------------------ /** * Constructs a new label. */ public Label() { } // ------------------------------------------------------------------------ // Methods to compute offsets and to manage forward references // ------------------------------------------------------------------------ /** * Returns the offset corresponding to this label. This offset is computed * from the start of the method's bytecode. This method is intended for * {@link Attribute} sub classes, and is normally not needed by class * generators or adapters. * * @return the offset corresponding to this label. * @throws IllegalStateException * if this label is not resolved yet. */ public int getOffset() { if ((status & RESOLVED) == 0) { throw new IllegalStateException( "Label offset position has not been resolved yet"); } return position; } /** * Puts a reference to this label in the bytecode of a method. If the * position of the label is known, the offset is computed and written * directly. Otherwise, a null offset is written and a new forward reference * is declared for this label. * * @param owner * the code writer that calls this method. * @param out * the bytecode of the method. * @param source * the position of first byte of the bytecode instruction that * contains this label. * @param wideOffset * true if the reference must be stored in 4 bytes, or * false if it must be stored with 2 bytes. * @throws IllegalArgumentException * if this label has not been created by the given code writer. */ void put(final MethodWriter owner, final ByteVector out, final int source, final boolean wideOffset) { if ((status & RESOLVED) == 0) { if (wideOffset) { addReference(-1 - source, out.length); out.putInt(-1); } else { addReference(source, out.length); out.putShort(-1); } } else { if (wideOffset) { out.putInt(position - source); } else { out.putShort(position - source); } } } /** * Adds a forward reference to this label. This method must be called only * for a true forward reference, i.e. only if this label is not resolved * yet. For backward references, the offset of the reference can be, and * must be, computed and stored directly. * * @param sourcePosition * the position of the referencing instruction. This position * will be used to compute the offset of this forward reference. * @param referencePosition * the position where the offset for this forward reference must * be stored. */ private void addReference(final int sourcePosition, final int referencePosition) { if (srcAndRefPositions == null) { srcAndRefPositions = new int[6]; } if (referenceCount >= srcAndRefPositions.length) { int[] a = new int[srcAndRefPositions.length + 6]; System.arraycopy(srcAndRefPositions, 0, a, 0, srcAndRefPositions.length); srcAndRefPositions = a; } srcAndRefPositions[referenceCount++] = sourcePosition; srcAndRefPositions[referenceCount++] = referencePosition; } /** * Resolves all forward references to this label. This method must be called * when this label is added to the bytecode of the method, i.e. when its * position becomes known. This method fills in the blanks that where left * in the bytecode by each forward reference previously added to this label. * * @param owner * the code writer that calls this method. * @param position * the position of this label in the bytecode. * @param data * the bytecode of the method. * @return true if a blank that was left for this label was to * small to store the offset. In such a case the corresponding jump * instruction is replaced with a pseudo instruction (using unused * opcodes) using an unsigned two bytes offset. These pseudo * instructions will need to be replaced with true instructions with * wider offsets (4 bytes instead of 2). This is done in * {@link MethodWriter#resizeInstructions}. * @throws IllegalArgumentException * if this label has already been resolved, or if it has not * been created by the given code writer. */ boolean resolve(final MethodWriter owner, final int position, final byte[] data) { boolean needUpdate = false; this.status |= RESOLVED; this.position = position; int i = 0; while (i < referenceCount) { int source = srcAndRefPositions[i++]; int reference = srcAndRefPositions[i++]; int offset; if (source >= 0) { offset = position - source; if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) { /* * changes the opcode of the jump instruction, in order to * be able to find it later (see resizeInstructions in * MethodWriter). These temporary opcodes are similar to * jump instruction opcodes, except that the 2 bytes offset * is unsigned (and can therefore represent values from 0 to * 65535, which is sufficient since the size of a method is * limited to 65535 bytes). */ int opcode = data[reference - 1] & 0xFF; if (opcode <= Opcodes.JSR) { // changes IFEQ ... JSR to opcodes 202 to 217 data[reference - 1] = (byte) (opcode + 49); } else { // changes IFNULL and IFNONNULL to opcodes 218 and 219 data[reference - 1] = (byte) (opcode + 20); } needUpdate = true; } data[reference++] = (byte) (offset >>> 8); data[reference] = (byte) offset; } else { offset = position + source + 1; data[reference++] = (byte) (offset >>> 24); data[reference++] = (byte) (offset >>> 16); data[reference++] = (byte) (offset >>> 8); data[reference] = (byte) offset; } } return needUpdate; } /** * Returns the first label of the series to which this label belongs. For an * isolated label or for the first label in a series of successive labels, * this method returns the label itself. For other labels it returns the * first label of the series. * * @return the first label of the series to which this label belongs. */ Label getFirst() { return !ClassReader.FRAMES || frame == null ? this : frame.owner; } // ------------------------------------------------------------------------ // Methods related to subroutines // ------------------------------------------------------------------------ /** * Returns true is this basic block belongs to the given subroutine. * * @param id * a subroutine id. * @return true is this basic block belongs to the given subroutine. */ boolean inSubroutine(final long id) { if ((status & Label.VISITED) != 0) { return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0; } return false; } /** * Returns true if this basic block and the given one belong to a common * subroutine. * * @param block * another basic block. * @return true if this basic block and the given one belong to a common * subroutine. */ boolean inSameSubroutine(final Label block) { if ((status & VISITED) == 0 || (block.status & VISITED) == 0) { return false; } for (int i = 0; i < srcAndRefPositions.length; ++i) { if ((srcAndRefPositions[i] & block.srcAndRefPositions[i]) != 0) { return true; } } return false; } /** * Marks this basic block as belonging to the given subroutine. * * @param id * a subroutine id. * @param nbSubroutines * the total number of subroutines in the method. */ void addToSubroutine(final long id, final int nbSubroutines) { if ((status & VISITED) == 0) { status |= VISITED; srcAndRefPositions = new int[(nbSubroutines - 1) / 32 + 1]; } srcAndRefPositions[(int) (id >>> 32)] |= (int) id; } /** * Finds the basic blocks that belong to a given subroutine, and marks these * blocks as belonging to this subroutine. This method follows the control * flow graph to find all the blocks that are reachable from the current * block WITHOUT following any JSR target. * * @param JSR * a JSR block that jumps to this subroutine. If this JSR is not * null it is added to the successor of the RET blocks found in * the subroutine. * @param id * the id of this subroutine. * @param nbSubroutines * the total number of subroutines in the method. */ void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) { // user managed stack of labels, to avoid using a recursive method // (recursivity can lead to stack overflow with very large methods) Label stack = this; while (stack != null) { // removes a label l from the stack Label l = stack; stack = l.next; l.next = null; if (JSR != null) { if ((l.status & VISITED2) != 0) { continue; } l.status |= VISITED2; // adds JSR to the successors of l, if it is a RET block if ((l.status & RET) != 0) { if (!l.inSameSubroutine(JSR)) { Edge e = new Edge(); e.info = l.inputStackTop; e.successor = JSR.successors.successor; e.next = l.successors; l.successors = e; } } } else { // if the l block already belongs to subroutine 'id', continue if (l.inSubroutine(id)) { continue; } // marks the l block as belonging to subroutine 'id' l.addToSubroutine(id, nbSubroutines); } // pushes each successor of l on the stack, except JSR targets Edge e = l.successors; while (e != null) { // if the l block is a JSR block, then 'l.successors.next' leads // to the JSR target (see {@link #visitJumpInsn}) and must // therefore not be followed if ((l.status & Label.JSR) == 0 || e != l.successors.next) { // pushes e.successor on the stack if it not already added if (e.successor.next == null) { e.successor.next = stack; stack = e.successor; } } e = e.next; } } } // ------------------------------------------------------------------------ // Overriden Object methods // ------------------------------------------------------------------------ /** * Returns a string representation of this label. * * @return a string representation of this label. */ @Override public String toString() { return "L" + System.identityHashCode(this); } } libasm4-java-4.1/src/org/objectweb/asm/MethodVisitor.java000066400000000000000000000634061207310427500234070ustar00rootroot00000000000000/*** * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.objectweb.asm; /** * A visitor to visit a Java method. The methods of this class must be called in * the following order: [ visitAnnotationDefault ] ( * visitAnnotation | visitParameterAnnotation | * visitAttribute )* [ visitCode ( visitFrame | * visitXInsn
| visitLabel | * visitTryCatchBlock | visitLocalVariable | * visitLineNumber )* visitMaxs ] visitEnd. In * addition, the visitXInsn
and visitLabel methods * must be called in the sequential order of the bytecode instructions of the * visited code, visitTryCatchBlock must be called before the * labels passed as arguments have been visited, and the * visitLocalVariable and visitLineNumber methods must be * called after the labels passed as arguments have been visited. * * @author Eric Bruneton */ public abstract class MethodVisitor { /** * The ASM API version implemented by this visitor. The value of this field * must be one of {@link Opcodes#ASM4}. */ protected final int api; /** * The method visitor to which this visitor must delegate method calls. May * be null. */ protected MethodVisitor mv; /** * Constructs a new {@link MethodVisitor}. * * @param api * the ASM API version implemented by this visitor. Must be one * of {@link Opcodes#ASM4}. */ public MethodVisitor(final int api) { this(api, null); } /** * Constructs a new {@link MethodVisitor}. * * @param api * the ASM API version implemented by this visitor. Must be one * of {@link Opcodes#ASM4}. * @param mv * the method visitor to which this visitor must delegate method * calls. May be null. */ public MethodVisitor(final int api, final MethodVisitor mv) { if (api != Opcodes.ASM4) { throw new IllegalArgumentException(); } this.api = api; this.mv = mv; } // ------------------------------------------------------------------------- // Annotations and non standard attributes // ------------------------------------------------------------------------- /** * Visits the default value of this annotation interface method. * * @return a visitor to the visit the actual default value of this * annotation interface method, or null if this visitor is * not interested in visiting this default value. The 'name' * parameters passed to the methods of this annotation visitor are * ignored. Moreover, exacly one visit method must be called on this * annotation visitor, followed by visitEnd. */ public AnnotationVisitor visitAnnotationDefault() { if (mv != null) { return mv.visitAnnotationDefault(); } return null; } /** * Visits an annotation of this method. * * @param desc * the class descriptor of the annotation class. * @param visible * true if the annotation is visible at runtime. * @return a visitor to visit the annotation values, or null if * this visitor is not interested in visiting this annotation. */ public AnnotationVisitor visitAnnotation(String desc, boolean visible) { if (mv != null) { return mv.visitAnnotation(desc, visible); } return null; } /** * Visits an annotation of a parameter this method. * * @param parameter * the parameter index. * @param desc * the class descriptor of the annotation class. * @param visible * true if the annotation is visible at runtime. * @return a visitor to visit the annotation values, or null if * this visitor is not interested in visiting this annotation. */ public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) { if (mv != null) { return mv.visitParameterAnnotation(parameter, desc, visible); } return null; } /** * Visits a non standard attribute of this method. * * @param attr * an attribute. */ public void visitAttribute(Attribute attr) { if (mv != null) { mv.visitAttribute(attr); } } /** * Starts the visit of the method's code, if any (i.e. non abstract method). */ public void visitCode() { if (mv != null) { mv.visitCode(); } } /** * Visits the current state of the local variables and operand stack * elements. This method must(*) be called just before any * instruction i that follows an unconditional branch instruction * such as GOTO or THROW, that is the target of a jump instruction, or that * starts an exception handler block. The visited types must describe the * values of the local variables and of the operand stack elements just * before i is executed.
*
* (*) this is mandatory only for classes whose version is greater than or * equal to {@link Opcodes#V1_6 V1_6}.
*
* The frames of a method must be given either in expanded form, or in * compressed form (all frames must use the same format, i.e. you must not * mix expanded and compressed frames within a single method): *
    *
  • In expanded form, all frames must have the F_NEW type.
  • *
  • In compressed form, frames are basically "deltas" from the state of * the previous frame: *
      *
    • {@link Opcodes#F_SAME} representing frame with exactly the same * locals as the previous frame and with the empty stack.
    • *
    • {@link Opcodes#F_SAME1} representing frame with exactly the same * locals as the previous frame and with single value on the stack ( * nStack is 1 and stack[0] contains value for the * type of the stack item).
    • *
    • {@link Opcodes#F_APPEND} representing frame with current locals are * the same as the locals in the previous frame, except that additional * locals are defined (nLocal is 1, 2 or 3 and * local elements contains values representing added types).
    • *
    • {@link Opcodes#F_CHOP} representing frame with current locals are the * same as the locals in the previous frame, except that the last 1-3 locals * are absent and with the empty stack (nLocals is 1, 2 or 3).
    • *
    • {@link Opcodes#F_FULL} representing complete frame data.
    • *
    *

* In both cases the first frame, corresponding to the method's parameters * and access flags, is implicit and must not be visited. Also, it is * illegal to visit two or more frames for the same code location (i.e., at * least one instruction must be visited between two calls to visitFrame). * * @param type * the type of this stack map frame. Must be * {@link Opcodes#F_NEW} for expanded frames, or * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for * compressed frames. * @param nLocal * the number of local variables in the visited frame. * @param local * the local variable types in this frame. This array must not be * modified. Primitive types are represented by * {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, * {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or * {@link Opcodes#UNINITIALIZED_THIS} (long and double are * represented by a single element). Reference types are * represented by String objects (representing internal names), * and uninitialized types by Label objects (this label * designates the NEW instruction that created this uninitialized * value). * @param nStack * the number of operand stack elements in the visited frame. * @param stack * the operand stack types in this frame. This array must not be * modified. Its content has the same format as the "local" * array. * @throws IllegalStateException * if a frame is visited just after another one, without any * instruction between the two (unless this frame is a * Opcodes#F_SAME frame, in which case it is silently ignored). */ public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { if (mv != null) { mv.visitFrame(type, nLocal, local, nStack, stack); } } // ------------------------------------------------------------------------- // Normal instructions // ------------------------------------------------------------------------- /** * Visits a zero operand instruction. * * @param opcode * the opcode of the instruction to be visited. This opcode is * either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, * ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, * FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, * LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, * SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, * DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, * IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM, * FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, * IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D, * L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S, * LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN, * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER, * or MONITOREXIT. */ public void visitInsn(int opcode) { if (mv != null) { mv.visitInsn(opcode); } } /** * Visits an instruction with a single int operand. * * @param opcode * the opcode of the instruction to be visited. This opcode is * either BIPUSH, SIPUSH or NEWARRAY. * @param operand * the operand of the instruction to be visited.
* When opcode is BIPUSH, operand value should be between * Byte.MIN_VALUE and Byte.MAX_VALUE.
* When opcode is SIPUSH, operand value should be between * Short.MIN_VALUE and Short.MAX_VALUE.
* When opcode is NEWARRAY, operand value should be one of * {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR}, * {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE}, * {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT}, * {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}. */ public void visitIntInsn(int opcode, int operand) { if (mv != null) { mv.visitIntInsn(opcode, operand); } } /** * Visits a local variable instruction. A local variable instruction is an * instruction that loads or stores the value of a local variable. * * @param opcode * the opcode of the local variable instruction to be visited. * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, * ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET. * @param var * the operand of the instruction to be visited. This operand is * the index of a local variable. */ public void visitVarInsn(int opcode, int var) { if (mv != null) { mv.visitVarInsn(opcode, var); } } /** * Visits a type instruction. A type instruction is an instruction that * takes the internal name of a class as parameter. * * @param opcode * the opcode of the type instruction to be visited. This opcode * is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF. * @param type * the operand of the instruction to be visited. This operand * must be the internal name of an object or array class (see * {@link Type#getInternalName() getInternalName}). */ public void visitTypeInsn(int opcode, String type) { if (mv != null) { mv.visitTypeInsn(opcode, type); } } /** * Visits a field instruction. A field instruction is an instruction that * loads or stores the value of a field of an object. * * @param opcode * the opcode of the type instruction to be visited. This opcode * is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD. * @param owner * the internal name of the field's owner class (see * {@link Type#getInternalName() getInternalName}). * @param name * the field's name. * @param desc * the field's descriptor (see {@link Type Type}). */ public void visitFieldInsn(int opcode, String owner, String name, String desc) { if (mv != null) { mv.visitFieldInsn(opcode, owner, name, desc); } } /** * Visits a method instruction. A method instruction is an instruction that * invokes a method. * * @param opcode * the opcode of the type instruction to be visited. This opcode * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or * INVOKEINTERFACE. * @param owner * the internal name of the method's owner class (see * {@link Type#getInternalName() getInternalName}). * @param name * the method's name. * @param desc * the method's descriptor (see {@link Type Type}). */ public void visitMethodInsn(int opcode, String owner, String name, String desc) { if (mv != null) { mv.visitMethodInsn(opcode, owner, name, desc); } } /** * Visits an invokedynamic instruction. * * @param name * the method's name. * @param desc * the method's descriptor (see {@link Type Type}). * @param bsm * the bootstrap method. * @param bsmArgs * the bootstrap method constant arguments. Each argument must be * an {@link Integer}, {@link Float}, {@link Long}, * {@link Double}, {@link String}, {@link Type} or {@link Handle} * value. This method is allowed to modify the content of the * array so a caller should expect that this array may change. */ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { if (mv != null) { mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); } } /** * Visits a jump instruction. A jump instruction is an instruction that may * jump to another instruction. * * @param opcode * the opcode of the type instruction to be visited. This opcode * is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, * IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL. * @param label * the operand of the instruction to be visited. This operand is * a label that designates the instruction to which the jump * instruction may jump. */ public void visitJumpInsn(int opcode, Label label) { if (mv != null) { mv.visitJumpInsn(opcode, label); } } /** * Visits a label. A label designates the instruction that will be visited * just after it. * * @param label * a {@link Label Label} object. */ public void visitLabel(Label label) { if (mv != null) { mv.visitLabel(label); } } // ------------------------------------------------------------------------- // Special instructions // ------------------------------------------------------------------------- /** * Visits a LDC instruction. Note that new constant types may be added in * future versions of the Java Virtual Machine. To easily detect new * constant types, implementations of this method should check for * unexpected constant types, like this: * *
     * if (cst instanceof Integer) {
     *     // ...
     * } else if (cst instanceof Float) {
     *     // ...
     * } else if (cst instanceof Long) {
     *     // ...
     * } else if (cst instanceof Double) {
     *     // ...
     * } else if (cst instanceof String) {
     *     // ...
     * } else if (cst instanceof Type) {
     *     int sort = ((Type) cst).getSort();
     *     if (sort == Type.OBJECT) {
     *         // ...
     *     } else if (sort == Type.ARRAY) {
     *         // ...
     *     } else if (sort == Type.METHOD) {
     *         // ...
     *     } else {
     *         // throw an exception
     *     }
     * } else if (cst instanceof Handle) {
     *     // ...
     * } else {
     *     // throw an exception
     * }
     * 
* * @param cst * the constant to be loaded on the stack. This parameter must be * a non null {@link Integer}, a {@link Float}, a {@link Long}, a * {@link Double}, a {@link String}, a {@link Type} of OBJECT or * ARRAY sort for .class constants, for classes whose * version is 49.0, a {@link Type} of METHOD sort or a * {@link Handle} for MethodType and MethodHandle constants, for * classes whose version is 51.0. */ public void visitLdcInsn(Object cst) { if (mv != null) { mv.visitLdcInsn(cst); } } /** * Visits an IINC instruction. * * @param var * index of the local variable to be incremented. * @param increment * amount to increment the local variable by. */ public void visitIincInsn(int var, int increment) { if (mv != null) { mv.visitIincInsn(var, increment); } } /** * Visits a TABLESWITCH instruction. * * @param min * the minimum key value. * @param max * the maximum key value. * @param dflt * beginning of the default handler block. * @param labels * beginnings of the handler blocks. labels[i] is the * beginning of the handler block for the min + i key. */ public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) { if (mv != null) { mv.visitTableSwitchInsn(min, max, dflt, labels); } } /** * Visits a LOOKUPSWITCH instruction. * * @param dflt * beginning of the default handler block. * @param keys * the values of the keys. * @param labels * beginnings of the handler blocks. labels[i] is the * beginning of the handler block for the keys[i] key. */ public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { if (mv != null) { mv.visitLookupSwitchInsn(dflt, keys, labels); } } /** * Visits a MULTIANEWARRAY instruction. * * @param desc * an array type descriptor (see {@link Type Type}). * @param dims * number of dimensions of the array to allocate. */ public void visitMultiANewArrayInsn(String desc, int dims) { if (mv != null) { mv.visitMultiANewArrayInsn(desc, dims); } } // ------------------------------------------------------------------------- // Exceptions table entries, debug information, max stack and max locals // ------------------------------------------------------------------------- /** * Visits a try catch block. * * @param start * beginning of the exception handler's scope (inclusive). * @param end * end of the exception handler's scope (exclusive). * @param handler * beginning of the exception handler's code. * @param type * internal name of the type of exceptions handled by the * handler, or null to catch any exceptions (for * "finally" blocks). * @throws IllegalArgumentException * if one of the labels has already been visited by this visitor * (by the {@link #visitLabel visitLabel} method). */ public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { if (mv != null) { mv.visitTryCatchBlock(start, end, handler, type); } } /** * Visits a local variable declaration. * * @param name * the name of a local variable. * @param desc * the type descriptor of this local variable. * @param signature * the type signature of this local variable. May be * null if the local variable type does not use generic * types. * @param start * the first instruction corresponding to the scope of this local * variable (inclusive). * @param end * the last instruction corresponding to the scope of this local * variable (exclusive). * @param index * the local variable's index. * @throws IllegalArgumentException * if one of the labels has not already been visited by this * visitor (by the {@link #visitLabel visitLabel} method). */ public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { if (mv != null) { mv.visitLocalVariable(name, desc, signature, start, end, index); } } /** * Visits a line number declaration. * * @param line * a line number. This number refers to the source file from * which the class was compiled. * @param start * the first instruction corresponding to this line number. * @throws IllegalArgumentException * if start has not already been visited by this * visitor (by the {@link #visitLabel visitLabel} method). */ public void visitLineNumber(int line, Label start) { if (mv != null) { mv.visitLineNumber(line, start); } } /** * Visits the maximum stack size and the maximum number of local variables * of the method. * * @param maxStack * maximum stack size of the method. * @param maxLocals * maximum number of local variables for the method. */ public void visitMaxs(int maxStack, int maxLocals) { if (mv != null) { mv.visitMaxs(maxStack, maxLocals); } } /** * Visits the end of the method. This method, which is the last one to be * called, is used to inform the visitor that all the annotations and * attributes of the method have been visited. */ public void visitEnd() { if (mv != null) { mv.visitEnd(); } } } libasm4-java-4.1/src/org/objectweb/asm/MethodWriter.java000066400000000000000000003110471207310427500232210ustar00rootroot00000000000000/*** * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.objectweb.asm; /** * A {@link MethodVisitor} that generates methods in bytecode form. Each visit * method of this class appends the bytecode corresponding to the visited * instruction to a byte vector, in the order these methods are called. * * @author Eric Bruneton * @author Eugene Kuleshov */ class MethodWriter extends MethodVisitor { /** * Pseudo access flag used to denote constructors. */ static final int ACC_CONSTRUCTOR = 0x80000; /** * Frame has exactly the same locals as the previous stack map frame and * number of stack items is zero. */ static final int SAME_FRAME = 0; // to 63 (0-3f) /** * Frame has exactly the same locals as the previous stack map frame and * number of stack items is 1 */ static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; // to 127 (40-7f) /** * Reserved for future use */ static final int RESERVED = 128; /** * Frame has exactly the same locals as the previous stack map frame and * number of stack items is 1. Offset is bigger then 63; */ static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247; // f7 /** * Frame where current locals are the same as the locals in the previous * frame, except that the k last locals are absent. The value of k is given * by the formula 251-frame_type. */ static final int CHOP_FRAME = 248; // to 250 (f8-fA) /** * Frame has exactly the same locals as the previous stack map frame and * number of stack items is zero. Offset is bigger then 63; */ static final int SAME_FRAME_EXTENDED = 251; // fb /** * Frame where current locals are the same as the locals in the previous * frame, except that k additional locals are defined. The value of k is * given by the formula frame_type-251. */ static final int APPEND_FRAME = 252; // to 254 // fc-fe /** * Full frame */ static final int FULL_FRAME = 255; // ff /** * Indicates that the stack map frames must be recomputed from scratch. In * this case the maximum stack size and number of local variables is also * recomputed from scratch. * * @see #compute */ private static final int FRAMES = 0; /** * Indicates that the maximum stack size and number of local variables must * be automatically computed. * * @see #compute */ private static final int MAXS = 1; /** * Indicates that nothing must be automatically computed. * * @see #compute */ private static final int NOTHING = 2; /** * The class writer to which this method must be added. */ final ClassWriter cw; /** * Access flags of this method. */ private int access; /** * The index of the constant pool item that contains the name of this * method. */ private final int name; /** * The index of the constant pool item that contains the descriptor of this * method. */ private final int desc; /** * The descriptor of this method. */ private final String descriptor; /** * The signature of this method. */ String signature; /** * If not zero, indicates that the code of this method must be copied from * the ClassReader associated to this writer in cw.cr. More * precisely, this field gives the index of the first byte to copied from * cw.cr.b. */ int classReaderOffset; /** * If not zero, indicates that the code of this method must be copied from * the ClassReader associated to this writer in cw.cr. More * precisely, this field gives the number of bytes to copied from * cw.cr.b. */ int classReaderLength; /** * Number of exceptions that can be thrown by this method. */ int exceptionCount; /** * The exceptions that can be thrown by this method. More precisely, this * array contains the indexes of the constant pool items that contain the * internal names of these exception classes. */ int[] exceptions; /** * The annotation default attribute of this method. May be null. */ private ByteVector annd; /** * The runtime visible annotations of this method. May be null. */ private AnnotationWriter anns; /** * The runtime invisible annotations of this method. May be null. */ private AnnotationWriter ianns; /** * The runtime visible parameter annotations of this method. May be * null. */ private AnnotationWriter[] panns; /** * The runtime invisible parameter annotations of this method. May be * null. */ private AnnotationWriter[] ipanns; /** * The number of synthetic parameters of this method. */ private int synthetics; /** * The non standard attributes of the method. */ private Attribute attrs; /** * The bytecode of this method. */ private ByteVector code = new ByteVector(); /** * Maximum stack size of this method. */ private int maxStack; /** * Maximum number of local variables for this method. */ private int maxLocals; /** * Number of local variables in the current stack map frame. */ private int currentLocals; /** * Number of stack map frames in the StackMapTable attribute. */ private int frameCount; /** * The StackMapTable attribute. */ private ByteVector stackMap; /** * The offset of the last frame that was written in the StackMapTable * attribute. */ private int previousFrameOffset; /** * The last frame that was written in the StackMapTable attribute. * * @see #frame */ private int[] previousFrame; /** * The current stack map frame. The first element contains the offset of the * instruction to which the frame corresponds, the second element is the * number of locals and the third one is the number of stack elements. The * local variables start at index 3 and are followed by the operand stack * values. In summary frame[0] = offset, frame[1] = nLocal, frame[2] = * nStack, frame[3] = nLocal. All types are encoded as integers, with the * same format as the one used in {@link Label}, but limited to BASE types. */ private int[] frame; /** * Number of elements in the exception handler list. */ private int handlerCount; /** * The first element in the exception handler list. */ private Handler firstHandler; /** * The last element in the exception handler list. */ private Handler lastHandler; /** * Number of entries in the LocalVariableTable attribute. */ private int localVarCount; /** * The LocalVariableTable attribute. */ private ByteVector localVar; /** * Number of entries in the LocalVariableTypeTable attribute. */ private int localVarTypeCount; /** * The LocalVariableTypeTable attribute. */ private ByteVector localVarType; /** * Number of entries in the LineNumberTable attribute. */ private int lineNumberCount; /** * The LineNumberTable attribute. */ private ByteVector lineNumber; /** * The non standard attributes of the method's code. */ private Attribute cattrs; /** * Indicates if some jump instructions are too small and need to be resized. */ private boolean resize; /** * The number of subroutines in this method. */ private int subroutines; // ------------------------------------------------------------------------ /* * Fields for the control flow graph analysis algorithm (used to compute the * maximum stack size). A control flow graph contains one node per "basic * block", and one edge per "jump" from one basic block to another. Each * node (i.e., each basic block) is represented by the Label object that * corresponds to the first instruction of this basic block. Each node also * stores the list of its successors in the graph, as a linked list of Edge * objects. */ /** * Indicates what must be automatically computed. * * @see #FRAMES * @see #MAXS * @see #NOTHING */ private final int compute; /** * A list of labels. This list is the list of basic blocks in the method, * i.e. a list of Label objects linked to each other by their * {@link Label#successor} field, in the order they are visited by * {@link MethodVisitor#visitLabel}, and starting with the first basic * block. */ private Label labels; /** * The previous basic block. */ private Label previousBlock; /** * The current basic block. */ private Label currentBlock; /** * The (relative) stack size after the last visited instruction. This size * is relative to the beginning of the current basic block, i.e., the true * stack size after the last visited instruction is equal to the * {@link Label#inputStackTop beginStackSize} of the current basic block * plus stackSize. */ private int stackSize; /** * The (relative) maximum stack size after the last visited instruction. * This size is relative to the beginning of the current basic block, i.e., * the true maximum stack size after the last visited instruction is equal * to the {@link Label#inputStackTop beginStackSize} of the current basic * block plus stackSize. */ private int maxStackSize; // ------------------------------------------------------------------------ // Constructor // ------------------------------------------------------------------------ /** * Constructs a new {@link MethodWriter}. * * @param cw * the class writer in which the method must be added. * @param access * the method's access flags (see {@link Opcodes}). * @param name * the method's name. * @param desc * the method's descriptor (see {@link Type}). * @param signature * the method's signature. May be null. * @param exceptions * the internal names of the method's exceptions. May be * null. * @param computeMaxs * true if the maximum stack size and number of local * variables must be automatically computed. * @param computeFrames * true if the stack map tables must be recomputed from * scratch. */ MethodWriter(final ClassWriter cw, final int access, final String name, final String desc, final String signature, final String[] exceptions, final boolean computeMaxs, final boolean computeFrames) { super(Opcodes.ASM4); if (cw.firstMethod == null) { cw.firstMethod = this; } else { cw.lastMethod.mv = this; } cw.lastMethod = this; this.cw = cw; this.access = access; if ("".equals(name)) { this.access |= ACC_CONSTRUCTOR; } this.name = cw.newUTF8(name); this.desc = cw.newUTF8(desc); this.descriptor = desc; if (ClassReader.SIGNATURES) { this.signature = signature; } if (exceptions != null && exceptions.length > 0) { exceptionCount = exceptions.length; this.exceptions = new int[exceptionCount]; for (int i = 0; i < exceptionCount; ++i) { this.exceptions[i] = cw.newClass(exceptions[i]); } } this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING); if (computeMaxs || computeFrames) { // updates maxLocals int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2; if ((access & Opcodes.ACC_STATIC) != 0) { --size; } maxLocals = size; currentLocals = size; // creates and visits the label for the first basic block labels = new Label(); labels.status |= Label.PUSHED; visitLabel(labels); } } // ------------------------------------------------------------------------ // Implementation of the MethodVisitor abstract class // ------------------------------------------------------------------------ @Override public AnnotationVisitor visitAnnotationDefault() { if (!ClassReader.ANNOTATIONS) { return null; } annd = new ByteVector(); return new AnnotationWriter(cw, false, annd, null, 0); } @Override public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { if (!ClassReader.ANNOTATIONS) { return null; } ByteVector bv = new ByteVector(); // write type, and reserve space for values count bv.putShort(cw.newUTF8(desc)).putShort(0); AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); if (visible) { aw.next = anns; anns = aw; } else { aw.next = ianns; ianns = aw; } return aw; } @Override public AnnotationVisitor visitParameterAnnotation(final int parameter, final String desc, final boolean visible) { if (!ClassReader.ANNOTATIONS) { return null; } ByteVector bv = new ByteVector(); if ("Ljava/lang/Synthetic;".equals(desc)) { // workaround for a bug in javac with synthetic parameters // see ClassReader.readParameterAnnotations synthetics = Math.max(synthetics, parameter + 1); return new AnnotationWriter(cw, false, bv, null, 0); } // write type, and reserve space for values count bv.putShort(cw.newUTF8(desc)).putShort(0); AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2); if (visible) { if (panns == null) { panns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length]; } aw.next = panns[parameter]; panns[parameter] = aw; } else { if (ipanns == null) { ipanns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length]; } aw.next = ipanns[parameter]; ipanns[parameter] = aw; } return aw; } @Override public void visitAttribute(final Attribute attr) { if (attr.isCodeAttribute()) { attr.next = cattrs; cattrs = attr; } else { attr.next = attrs; attrs = attr; } } @Override public void visitCode() { } @Override public void visitFrame(final int type, final int nLocal, final Object[] local, final int nStack, final Object[] stack) { if (!ClassReader.FRAMES || compute == FRAMES) { return; } if (type == Opcodes.F_NEW) { if (previousFrame == null) { visitImplicitFirstFrame(); } currentLocals = nLocal; int frameIndex = startFrame(code.length, nLocal, nStack); for (int i = 0; i < nLocal; ++i) { if (local[i] instanceof String) { frame[frameIndex++] = Frame.OBJECT | cw.addType((String) local[i]); } else if (local[i] instanceof Integer) { frame[frameIndex++] = ((Integer) local[i]).intValue(); } else { frame[frameIndex++] = Frame.UNINITIALIZED | cw.addUninitializedType("", ((Label) local[i]).position); } } for (int i = 0; i < nStack; ++i) { if (stack[i] instanceof String) { frame[frameIndex++] = Frame.OBJECT | cw.addType((String) stack[i]); } else if (stack[i] instanceof Integer) { frame[frameIndex++] = ((Integer) stack[i]).intValue(); } else { frame[frameIndex++] = Frame.UNINITIALIZED | cw.addUninitializedType("", ((Label) stack[i]).position); } } endFrame(); } else { int delta; if (stackMap == null) { stackMap = new ByteVector(); delta = code.length; } else { delta = code.length - previousFrameOffset - 1; if (delta < 0) { if (type == Opcodes.F_SAME) { return; } else { throw new IllegalStateException(); } } } switch (type) { case Opcodes.F_FULL: currentLocals = nLocal; stackMap.putByte(FULL_FRAME).putShort(delta).putShort(nLocal); for (int i = 0; i < nLocal; ++i) { writeFrameType(local[i]); } stackMap.putShort(nStack); for (int i = 0; i < nStack; ++i) { writeFrameType(stack[i]); } break; case Opcodes.F_APPEND: currentLocals += nLocal; stackMap.putByte(SAME_FRAME_EXTENDED + nLocal).putShort(delta); for (int i = 0; i < nLocal; ++i) { writeFrameType(local[i]); } break; case Opcodes.F_CHOP: currentLocals -= nLocal; stackMap.putByte(SAME_FRAME_EXTENDED - nLocal).putShort(delta); break; case Opcodes.F_SAME: if (delta < 64) { stackMap.putByte(delta); } else { stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta); } break; case Opcodes.F_SAME1: if (delta < 64) { stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta); } else { stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) .putShort(delta); } writeFrameType(stack[0]); break; } previousFrameOffset = code.length; ++frameCount; } maxStack = Math.max(maxStack, nStack); maxLocals = Math.max(maxLocals, currentLocals); } @Override public void visitInsn(final int opcode) { // adds the instruction to the bytecode of the method code.putByte(opcode); // update currentBlock // Label currentBlock = this.currentBlock; if (currentBlock != null) { if (compute == FRAMES) { currentBlock.frame.execute(opcode, 0, null, null); } else { // updates current and max stack sizes int size = stackSize + Frame.SIZE[opcode]; if (size > maxStackSize) { maxStackSize = size; } stackSize = size; } // if opcode == ATHROW or xRETURN, ends current block (no successor) if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) || opcode == Opcodes.ATHROW) { noSuccessor(); } } } @Override public void visitIntInsn(final int opcode, final int operand) { // Label currentBlock = this.currentBlock; if (currentBlock != null) { if (compute == FRAMES) { currentBlock.frame.execute(opcode, operand, null, null); } else if (opcode != Opcodes.NEWARRAY) { // updates current and max stack sizes only for NEWARRAY // (stack size variation = 0 for BIPUSH or SIPUSH) int size = stackSize + 1; if (size > maxStackSize) { maxStackSize = size; } stackSize = size; } } // adds the instruction to the bytecode of the method if (opcode == Opcodes.SIPUSH) { code.put12(opcode, operand); } else { // BIPUSH or NEWARRAY code.put11(opcode, operand); } } @Override public void visitVarInsn(final int opcode, final int var) { // Label currentBlock = this.currentBlock; if (currentBlock != null) { if (compute == FRAMES) { currentBlock.frame.execute(opcode, var, null, null); } else { // updates current and max stack sizes if (opcode == Opcodes.RET) { // no stack change, but end of current block (no successor) currentBlock.status |= Label.RET; // save 'stackSize' here for future use // (see {@link #findSubroutineSuccessors}) currentBlock.inputStackTop = stackSize; noSuccessor(); } else { // xLOAD or xSTORE int size = stackSize + Frame.SIZE[opcode]; if (size > maxStackSize) { maxStackSize = size; } stackSize = size; } } } if (compute != NOTHING) { // updates max locals int n; if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) { n = var + 2; } else { n = var + 1; } if (n > maxLocals) { maxLocals = n; } } // adds the instruction to the bytecode of the method if (var < 4 && opcode != Opcodes.RET) { int opt; if (opcode < Opcodes.ISTORE) { /* ILOAD_0 */ opt = 26 + ((opcode - Opcodes.ILOAD) << 2) + var; } else { /* ISTORE_0 */ opt = 59 + ((opcode - Opcodes.ISTORE) << 2) + var; } code.putByte(opt); } else if (var >= 256) { code.putByte(196 /* WIDE */).put12(opcode, var); } else { code.put11(opcode, var); } if (opcode >= Opcodes.ISTORE && compute == FRAMES && handlerCount > 0) { visitLabel(new Label()); } } @Override public void visitTypeInsn(final int opcode, final String type) { Item i = cw.newClassItem(type); // Label currentBlock = this.currentBlock; if (currentBlock != null) { if (compute == FRAMES) { currentBlock.frame.execute(opcode, code.length, cw, i); } else if (opcode == Opcodes.NEW) { // updates current and max stack sizes only if opcode == NEW // (no stack change for ANEWARRAY, CHECKCAST, INSTANCEOF) int size = stackSize + 1; if (size > maxStackSize) { maxStackSize = size; } stackSize = size; } } // adds the instruction to the bytecode of the method code.put12(opcode, i.index); } @Override public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) { Item i = cw.newFieldItem(owner, name, desc); // Label currentBlock = this.currentBlock; if (currentBlock != null) { if (compute == FRAMES) { currentBlock.frame.execute(opcode, 0, cw, i); } else { int size; // computes the stack size variation char c = desc.charAt(0); switch (opcode) { case Opcodes.GETSTATIC: size = stackSize + (c == 'D' || c == 'J' ? 2 : 1); break; case Opcodes.PUTSTATIC: size = stackSize + (c == 'D' || c == 'J' ? -2 : -1); break; case Opcodes.GETFIELD: size = stackSize + (c == 'D' || c == 'J' ? 1 : 0); break; // case Constants.PUTFIELD: default: size = stackSize + (c == 'D' || c == 'J' ? -3 : -2); break; } // updates current and max stack sizes if (size > maxStackSize) { maxStackSize = size; } stackSize = size; } } // adds the instruction to the bytecode of the method code.put12(opcode, i.index); } @Override public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) { boolean itf = opcode == Opcodes.INVOKEINTERFACE; Item i = cw.newMethodItem(owner, name, desc, itf); int argSize = i.intVal; // Label currentBlock = this.currentBlock; if (currentBlock != null) { if (compute == FRAMES) { currentBlock.frame.execute(opcode, 0, cw, i); } else { /* * computes the stack size variation. In order not to recompute * several times this variation for the same Item, we use the * intVal field of this item to store this variation, once it * has been computed. More precisely this intVal field stores * the sizes of the arguments and of the return value * corresponding to desc. */ if (argSize == 0) { // the above sizes have not been computed yet, // so we compute them... argSize = Type.getArgumentsAndReturnSizes(desc); // ... and we save them in order // not to recompute them in the future i.intVal = argSize; } int size; if (opcode == Opcodes.INVOKESTATIC) { size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1; } else { size = stackSize - (argSize >> 2) + (argSize & 0x03); } // updates current and max stack sizes if (size > maxStackSize) { maxStackSize = size; } stackSize = size; } } // adds the instruction to the bytecode of the method if (itf) { if (argSize == 0) { argSize = Type.getArgumentsAndReturnSizes(desc); i.intVal = argSize; } code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0); } else { code.put12(opcode, i.index); } } @Override public void visitInvokeDynamicInsn(final String name, final String desc, final Handle bsm, final Object... bsmArgs) { Item i = cw.newInvokeDynamicItem(name, desc, bsm, bsmArgs); int argSize = i.intVal; // Label currentBlock = this.currentBlock; if (currentBlock != null) { if (compute == FRAMES) { currentBlock.frame.execute(Opcodes.INVOKEDYNAMIC, 0, cw, i); } else { /* * computes the stack size variation. In order not to recompute * several times this variation for the same Item, we use the * intVal field of this item to store this variation, once it * has been computed. More precisely this intVal field stores * the sizes of the arguments and of the return value * corresponding to desc. */ if (argSize == 0) { // the above sizes have not been computed yet, // so we compute them... argSize = Type.getArgumentsAndReturnSizes(desc); // ... and we save them in order // not to recompute them in the future i.intVal = argSize; } int size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1; // updates current and max stack sizes if (size > maxStackSize) { maxStackSize = size; } stackSize = size; } } // adds the instruction to the bytecode of the method code.put12(Opcodes.INVOKEDYNAMIC, i.index); code.putShort(0); } @Override public void visitJumpInsn(final int opcode, final Label label) { Label nextInsn = null; // Label currentBlock = this.currentBlock; if (currentBlock != null) { if (compute == FRAMES) { currentBlock.frame.execute(opcode, 0, null, null); // 'label' is the target of a jump instruction label.getFirst().status |= Label.TARGET; // adds 'label' as a successor of this basic block addSuccessor(Edge.NORMAL, label); if (opcode != Opcodes.GOTO) { // creates a Label for the next basic block nextInsn = new Label(); } } else { if (opcode == Opcodes.JSR) { if ((label.status & Label.SUBROUTINE) == 0) { label.status |= Label.SUBROUTINE; ++subroutines; } currentBlock.status |= Label.JSR; addSuccessor(stackSize + 1, label); // creates a Label for the next basic block nextInsn = new Label(); /* * note that, by construction in this method, a JSR block * has at least two successors in the control flow graph: * the first one leads the next instruction after the JSR, * while the second one leads to the JSR target. */ } else { // updates current stack size (max stack size unchanged // because stack size variation always negative in this // case) stackSize += Frame.SIZE[opcode]; addSuccessor(stackSize, label); } } } // adds the instruction to the bytecode of the method if ((label.status & Label.RESOLVED) != 0 && label.position - code.length < Short.MIN_VALUE) { /* * case of a backward jump with an offset < -32768. In this case we * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx * with IFNOTxxx GOTO_W , where IFNOTxxx is the * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where * designates the instruction just after the GOTO_W. */ if (opcode == Opcodes.GOTO) { code.putByte(200); // GOTO_W } else if (opcode == Opcodes.JSR) { code.putByte(201); // JSR_W } else { // if the IF instruction is transformed into IFNOT GOTO_W the // next instruction becomes the target of the IFNOT instruction if (nextInsn != null) { nextInsn.status |= Label.TARGET; } code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1); code.putShort(8); // jump offset code.putByte(200); // GOTO_W } label.put(this, code, code.length - 1, true); } else { /* * case of a backward jump with an offset >= -32768, or of a forward * jump with, of course, an unknown offset. In these cases we store * the offset in 2 bytes (which will be increased in * resizeInstructions, if needed). */ code.putByte(opcode); label.put(this, code, code.length - 1, false); } if (currentBlock != null) { if (nextInsn != null) { // if the jump instruction is not a GOTO, the next instruction // is also a successor of this instruction. Calling visitLabel // adds the label of this next instruction as a successor of the // current block, and starts a new basic block visitLabel(nextInsn); } if (opcode == Opcodes.GOTO) { noSuccessor(); } } } @Override public void visitLabel(final Label label) { // resolves previous forward references to label, if any resize |= label.resolve(this, code.length, code.data); // updates currentBlock if ((label.status & Label.DEBUG) != 0) { return; } if (compute == FRAMES) { if (currentBlock != null) { if (label.position == currentBlock.position) { // successive labels, do not start a new basic block currentBlock.status |= (label.status & Label.TARGET); label.frame = currentBlock.frame; return; } // ends current block (with one new successor) addSuccessor(Edge.NORMAL, label); } // begins a new current block currentBlock = label; if (label.frame == null) { label.frame = new Frame(); label.frame.owner = label; } // updates the basic block list if (previousBlock != null) { if (label.position == previousBlock.position) { previousBlock.status |= (label.status & Label.TARGET); label.frame = previousBlock.frame; currentBlock = previousBlock; return; } previousBlock.successor = label; } previousBlock = label; } else if (compute == MAXS) { if (currentBlock != null) { // ends current block (with one new successor) currentBlock.outputStackMax = maxStackSize; addSuccessor(stackSize, label); } // begins a new current block currentBlock = label; // resets the relative current and max stack sizes stackSize = 0; maxStackSize = 0; // updates the basic block list if (previousBlock != null) { previousBlock.successor = label; } previousBlock = label; } } @Override public void visitLdcInsn(final Object cst) { Item i = cw.newConstItem(cst); // Label currentBlock = this.currentBlock; if (currentBlock != null) { if (compute == FRAMES) { currentBlock.frame.execute(Opcodes.LDC, 0, cw, i); } else { int size; // computes the stack size variation if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) { size = stackSize + 2; } else { size = stackSize + 1; } // updates current and max stack sizes if (size > maxStackSize) { maxStackSize = size; } stackSize = size; } } // adds the instruction to the bytecode of the method int index = i.index; if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) { code.put12(20 /* LDC2_W */, index); } else if (index >= 256) { code.put12(19 /* LDC_W */, index); } else { code.put11(Opcodes.LDC, index); } } @Override public void visitIincInsn(final int var, final int increment) { if (currentBlock != null) { if (compute == FRAMES) { currentBlock.frame.execute(Opcodes.IINC, var, null, null); } } if (compute != NOTHING) { // updates max locals int n = var + 1; if (n > maxLocals) { maxLocals = n; } } // adds the instruction to the bytecode of the method if ((var > 255) || (increment > 127) || (increment < -128)) { code.putByte(196 /* WIDE */).put12(Opcodes.IINC, var) .putShort(increment); } else { code.putByte(Opcodes.IINC).put11(var, increment); } } @Override public void visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label... labels) { // adds the instruction to the bytecode of the method int source = code.length; code.putByte(Opcodes.TABLESWITCH); code.putByteArray(null, 0, (4 - code.length % 4) % 4); dflt.put(this, code, source, true); code.putInt(min).putInt(max); for (int i = 0; i < labels.length; ++i) { labels[i].put(this, code, source, true); } // updates currentBlock visitSwitchInsn(dflt, labels); } @Override public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) { // adds the instruction to the bytecode of the method int source = code.length; code.putByte(Opcodes.LOOKUPSWITCH); code.putByteArray(null, 0, (4 - code.length % 4) % 4); dflt.put(this, code, source, true); code.putInt(labels.length); for (int i = 0; i < labels.length; ++i) { code.putInt(keys[i]); labels[i].put(this, code, source, true); } // updates currentBlock visitSwitchInsn(dflt, labels); } private void visitSwitchInsn(final Label dflt, final Label[] labels) { // Label currentBlock = this.currentBlock; if (currentBlock != null) { if (compute == FRAMES) { currentBlock.frame.execute(Opcodes.LOOKUPSWITCH, 0, null, null); // adds current block successors addSuccessor(Edge.NORMAL, dflt); dflt.getFirst().status |= Label.TARGET; for (int i = 0; i < labels.length; ++i) { addSuccessor(Edge.NORMAL, labels[i]); labels[i].getFirst().status |= Label.TARGET; } } else { // updates current stack size (max stack size unchanged) --stackSize; // adds current block successors addSuccessor(stackSize, dflt); for (int i = 0; i < labels.length; ++i) { addSuccessor(stackSize, labels[i]); } } // ends current block noSuccessor(); } } @Override public void visitMultiANewArrayInsn(final String desc, final int dims) { Item i = cw.newClassItem(desc); // Label currentBlock = this.currentBlock; if (currentBlock != null) { if (compute == FRAMES) { currentBlock.frame.execute(Opcodes.MULTIANEWARRAY, dims, cw, i); } else { // updates current stack size (max stack size unchanged because // stack size variation always negative or null) stackSize += 1 - dims; } } // adds the instruction to the bytecode of the method code.put12(Opcodes.MULTIANEWARRAY, i.index).putByte(dims); } @Override public void visitTryCatchBlock(final Label start, final Label end, final Label handler, final String type) { ++handlerCount; Handler h = new Handler(); h.start = start; h.end = end; h.handler = handler; h.desc = type; h.type = type != null ? cw.newClass(type) : 0; if (lastHandler == null) { firstHandler = h; } else { lastHandler.next = h; } lastHandler = h; } @Override public void visitLocalVariable(final String name, final String desc, final String signature, final Label start, final Label end, final int index) { if (signature != null) { if (localVarType == null) { localVarType = new ByteVector(); } ++localVarTypeCount; localVarType.putShort(start.position) .putShort(end.position - start.position) .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(signature)) .putShort(index); } if (localVar == null) { localVar = new ByteVector(); } ++localVarCount; localVar.putShort(start.position) .putShort(end.position - start.position) .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(desc)) .putShort(index); if (compute != NOTHING) { // updates max locals char c = desc.charAt(0); int n = index + (c == 'J' || c == 'D' ? 2 : 1); if (n > maxLocals) { maxLocals = n; } } } @Override public void visitLineNumber(final int line, final Label start) { if (lineNumber == null) { lineNumber = new ByteVector(); } ++lineNumberCount; lineNumber.putShort(start.position); lineNumber.putShort(line); } @Override public void visitMaxs(final int maxStack, final int maxLocals) { if (ClassReader.FRAMES && compute == FRAMES) { // completes the control flow graph with exception handler blocks Handler handler = firstHandler; while (handler != null) { Label l = handler.start.getFirst(); Label h = handler.handler.getFirst(); Label e = handler.end.getFirst(); // computes the kind of the edges to 'h' String t = handler.desc == null ? "java/lang/Throwable" : handler.desc; int kind = Frame.OBJECT | cw.addType(t); // h is an exception handler h.status |= Label.TARGET; // adds 'h' as a successor of labels between 'start' and 'end' while (l != e) { // creates an edge to 'h' Edge b = new Edge(); b.info = kind; b.successor = h; // adds it to the successors of 'l' b.next = l.successors; l.successors = b; // goes to the next label l = l.successor; } handler = handler.next; } // creates and visits the first (implicit) frame Frame f = labels.frame; Type[] args = Type.getArgumentTypes(descriptor); f.initInputFrame(cw, access, args, this.maxLocals); visitFrame(f); /* * fix point algorithm: mark the first basic block as 'changed' * (i.e. put it in the 'changed' list) and, while there are changed * basic blocks, choose one, mark it as unchanged, and update its * successors (which can be changed in the process). */ int max = 0; Label changed = labels; while (changed != null) { // removes a basic block from the list of changed basic blocks Label l = changed; changed = changed.next; l.next = null; f = l.frame; // a reachable jump target must be stored in the stack map if ((l.status & Label.TARGET) != 0) { l.status |= Label.STORE; } // all visited labels are reachable, by definition l.status |= Label.REACHABLE; // updates the (absolute) maximum stack size int blockMax = f.inputStack.length + l.outputStackMax; if (blockMax > max) { max = blockMax; } // updates the successors of the current basic block Edge e = l.successors; while (e != null) { Label n = e.successor.getFirst(); boolean change = f.merge(cw, n.frame, e.info); if (change && n.next == null) { // if n has changed and is not already in the 'changed' // list, adds it to this list n.next = changed; changed = n; } e = e.next; } } // visits all the frames that must be stored in the stack map Label l = labels; while (l != null) { f = l.frame; if ((l.status & Label.STORE) != 0) { visitFrame(f); } if ((l.status & Label.REACHABLE) == 0) { // finds start and end of dead basic block Label k = l.successor; int start = l.position; int end = (k == null ? code.length : k.position) - 1; // if non empty basic block if (end >= start) { max = Math.max(max, 1); // replaces instructions with NOP ... NOP ATHROW for (int i = start; i < end; ++i) { code.data[i] = Opcodes.NOP; } code.data[end] = (byte) Opcodes.ATHROW; // emits a frame for this unreachable block int frameIndex = startFrame(start, 0, 1); frame[frameIndex] = Frame.OBJECT | cw.addType("java/lang/Throwable"); endFrame(); // removes the start-end range from the exception // handlers firstHandler = Handler.remove(firstHandler, l, k); } } l = l.successor; } handler = firstHandler; handlerCount = 0; while (handler != null) { handlerCount += 1; handler = handler.next; } this.maxStack = max; } else if (compute == MAXS) { // completes the control flow graph with exception handler blocks Handler handler = firstHandler; while (handler != null) { Label l = handler.start; Label h = handler.handler; Label e = handler.end; // adds 'h' as a successor of labels between 'start' and 'end' while (l != e) { // creates an edge to 'h' Edge b = new Edge(); b.info = Edge.EXCEPTION; b.successor = h; // adds it to the successors of 'l' if ((l.status & Label.JSR) == 0) { b.next = l.successors; l.successors = b; } else { // if l is a JSR block, adds b after the first two edges // to preserve the hypothesis about JSR block successors // order (see {@link #visitJumpInsn}) b.next = l.successors.next.next; l.successors.next.next = b; } // goes to the next label l = l.successor; } handler = handler.next; } if (subroutines > 0) { // completes the control flow graph with the RET successors /* * first step: finds the subroutines. This step determines, for * each basic block, to which subroutine(s) it belongs. */ // finds the basic blocks that belong to the "main" subroutine int id = 0; labels.visitSubroutine(null, 1, subroutines); // finds the basic blocks that belong to the real subroutines Label l = labels; while (l != null) { if ((l.status & Label.JSR) != 0) { // the subroutine is defined by l's TARGET, not by l Label subroutine = l.successors.next.successor; // if this subroutine has not been visited yet... if ((subroutine.status & Label.VISITED) == 0) { // ...assigns it a new id and finds its basic blocks id += 1; subroutine.visitSubroutine(null, (id / 32L) << 32 | (1L << (id % 32)), subroutines); } } l = l.successor; } // second step: finds the successors of RET blocks l = labels; while (l != null) { if ((l.status & Label.JSR) != 0) { Label L = labels; while (L != null) { L.status &= ~Label.VISITED2; L = L.successor; } // the subroutine is defined by l's TARGET, not by l Label subroutine = l.successors.next.successor; subroutine.visitSubroutine(l, 0, subroutines); } l = l.successor; } } /* * control flow analysis algorithm: while the block stack is not * empty, pop a block from this stack, update the max stack size, * compute the true (non relative) begin stack size of the * successors of this block, and push these successors onto the * stack (unless they have already been pushed onto the stack). * Note: by hypothesis, the {@link Label#inputStackTop} of the * blocks in the block stack are the true (non relative) beginning * stack sizes of these blocks. */ int max = 0; Label stack = labels; while (stack != null) { // pops a block from the stack Label l = stack; stack = stack.next; // computes the true (non relative) max stack size of this block int start = l.inputStackTop; int blockMax = start + l.outputStackMax; // updates the global max stack size if (blockMax > max) { max = blockMax; } // analyzes the successors of the block Edge b = l.successors; if ((l.status & Label.JSR) != 0) { // ignores the first edge of JSR blocks (virtual successor) b = b.next; } while (b != null) { l = b.successor; // if this successor has not already been pushed... if ((l.status & Label.PUSHED) == 0) { // computes its true beginning stack size... l.inputStackTop = b.info == Edge.EXCEPTION ? 1 : start + b.info; // ...and pushes it onto the stack l.status |= Label.PUSHED; l.next = stack; stack = l; } b = b.next; } } this.maxStack = Math.max(maxStack, max); } else { this.maxStack = maxStack; this.maxLocals = maxLocals; } } @Override public void visitEnd() { } // ------------------------------------------------------------------------ // Utility methods: control flow analysis algorithm // ------------------------------------------------------------------------ /** * Adds a successor to the {@link #currentBlock currentBlock} block. * * @param info * information about the control flow edge to be added. * @param successor * the successor block to be added to the current block. */ private void addSuccessor(final int info, final Label successor) { // creates and initializes an Edge object... Edge b = new Edge(); b.info = info; b.successor = successor; // ...and adds it to the successor list of the currentBlock block b.next = currentBlock.successors; currentBlock.successors = b; } /** * Ends the current basic block. This method must be used in the case where * the current basic block does not have any successor. */ private void noSuccessor() { if (compute == FRAMES) { Label l = new Label(); l.frame = new Frame(); l.frame.owner = l; l.resolve(this, code.length, code.data); previousBlock.successor = l; previousBlock = l; } else { currentBlock.outputStackMax = maxStackSize; } currentBlock = null; } // ------------------------------------------------------------------------ // Utility methods: stack map frames // ------------------------------------------------------------------------ /** * Visits a frame that has been computed from scratch. * * @param f * the frame that must be visited. */ private void visitFrame(final Frame f) { int i, t; int nTop = 0; int nLocal = 0; int nStack = 0; int[] locals = f.inputLocals; int[] stacks = f.inputStack; // computes the number of locals (ignores TOP types that are just after // a LONG or a DOUBLE, and all trailing TOP types) for (i = 0; i < locals.length; ++i) { t = locals[i]; if (t == Frame.TOP) { ++nTop; } else { nLocal += nTop + 1; nTop = 0; } if (t == Frame.LONG || t == Frame.DOUBLE) { ++i; } } // computes the stack size (ignores TOP types that are just after // a LONG or a DOUBLE) for (i = 0; i < stacks.length; ++i) { t = stacks[i]; ++nStack; if (t == Frame.LONG || t == Frame.DOUBLE) { ++i; } } // visits the frame and its content int frameIndex = startFrame(f.owner.position, nLocal, nStack); for (i = 0; nLocal > 0; ++i, --nLocal) { t = locals[i]; frame[frameIndex++] = t; if (t == Frame.LONG || t == Frame.DOUBLE) { ++i; } } for (i = 0; i < stacks.length; ++i) { t = stacks[i]; frame[frameIndex++] = t; if (t == Frame.LONG || t == Frame.DOUBLE) { ++i; } } endFrame(); } /** * Visit the implicit first frame of this method. */ private void visitImplicitFirstFrame() { // There can be at most descriptor.length() + 1 locals int frameIndex = startFrame(0, descriptor.length() + 1, 0); if ((access & Opcodes.ACC_STATIC) == 0) { if ((access & ACC_CONSTRUCTOR) == 0) { frame[frameIndex++] = Frame.OBJECT | cw.addType(cw.thisName); } else { frame[frameIndex++] = 6; // Opcodes.UNINITIALIZED_THIS; } } int i = 1; loop: while (true) { int j = i; switch (descriptor.charAt(i++)) { case 'Z': case 'C': case 'B': case 'S': case 'I': frame[frameIndex++] = 1; // Opcodes.INTEGER; break; case 'F': frame[frameIndex++] = 2; // Opcodes.FLOAT; break; case 'J': frame[frameIndex++] = 4; // Opcodes.LONG; break; case 'D': frame[frameIndex++] = 3; // Opcodes.DOUBLE; break; case '[': while (descriptor.charAt(i) == '[') { ++i; } if (descriptor.charAt(i) == 'L') { ++i; while (descriptor.charAt(i) != ';') { ++i; } } frame[frameIndex++] = Frame.OBJECT | cw.addType(descriptor.substring(j, ++i)); break; case 'L': while (descriptor.charAt(i) != ';') { ++i; } frame[frameIndex++] = Frame.OBJECT | cw.addType(descriptor.substring(j + 1, i++)); break; default: break loop; } } frame[1] = frameIndex - 3; endFrame(); } /** * Starts the visit of a stack map frame. * * @param offset * the offset of the instruction to which the frame corresponds. * @param nLocal * the number of local variables in the frame. * @param nStack * the number of stack elements in the frame. * @return the index of the next element to be written in this frame. */ private int startFrame(final int offset, final int nLocal, final int nStack) { int n = 3 + nLocal + nStack; if (frame == null || frame.length < n) { frame = new int[n]; } frame[0] = offset; frame[1] = nLocal; frame[2] = nStack; return 3; } /** * Checks if the visit of the current frame {@link #frame} is finished, and * if yes, write it in the StackMapTable attribute. */ private void endFrame() { if (previousFrame != null) { // do not write the first frame if (stackMap == null) { stackMap = new ByteVector(); } writeFrame(); ++frameCount; } previousFrame = frame; frame = null; } /** * Compress and writes the current frame {@link #frame} in the StackMapTable * attribute. */ private void writeFrame() { int clocalsSize = frame[1]; int cstackSize = frame[2]; if ((cw.version & 0xFFFF) < Opcodes.V1_6) { stackMap.putShort(frame[0]).putShort(clocalsSize); writeFrameTypes(3, 3 + clocalsSize); stackMap.putShort(cstackSize); writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize); return; } int localsSize = previousFrame[1]; int type = FULL_FRAME; int k = 0; int delta; if (frameCount == 0) { delta = frame[0]; } else { delta = frame[0] - previousFrame[0] - 1; } if (cstackSize == 0) { k = clocalsSize - localsSize; switch (k) { case -3: case -2: case -1: type = CHOP_FRAME; localsSize = clocalsSize; break; case 0: type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED; break; case 1: case 2: case 3: type = APPEND_FRAME; break; } } else if (clocalsSize == localsSize && cstackSize == 1) { type = delta < 63 ? SAME_LOCALS_1_STACK_ITEM_FRAME : SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED; } if (type != FULL_FRAME) { // verify if locals are the same int l = 3; for (int j = 0; j < localsSize; j++) { if (frame[l] != previousFrame[l]) { type = FULL_FRAME; break; } l++; } } switch (type) { case SAME_FRAME: stackMap.putByte(delta); break; case SAME_LOCALS_1_STACK_ITEM_FRAME: stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta); writeFrameTypes(3 + clocalsSize, 4 + clocalsSize); break; case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED: stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED).putShort( delta); writeFrameTypes(3 + clocalsSize, 4 + clocalsSize); break; case SAME_FRAME_EXTENDED: stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta); break; case CHOP_FRAME: stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta); break; case APPEND_FRAME: stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta); writeFrameTypes(3 + localsSize, 3 + clocalsSize); break; // case FULL_FRAME: default: stackMap.putByte(FULL_FRAME).putShort(delta).putShort(clocalsSize); writeFrameTypes(3, 3 + clocalsSize); stackMap.putShort(cstackSize); writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize); } } /** * Writes some types of the current frame {@link #frame} into the * StackMapTableAttribute. This method converts types from the format used * in {@link Label} to the format used in StackMapTable attributes. In * particular, it converts type table indexes to constant pool indexes. * * @param start * index of the first type in {@link #frame} to write. * @param end * index of last type in {@link #frame} to write (exclusive). */ private void writeFrameTypes(final int start, final int end) { for (int i = start; i < end; ++i) { int t = frame[i]; int d = t & Frame.DIM; if (d == 0) { int v = t & Frame.BASE_VALUE; switch (t & Frame.BASE_KIND) { case Frame.OBJECT: stackMap.putByte(7).putShort( cw.newClass(cw.typeTable[v].strVal1)); break; case Frame.UNINITIALIZED: stackMap.putByte(8).putShort(cw.typeTable[v].intVal); break; default: stackMap.putByte(v); } } else { StringBuffer buf = new StringBuffer(); d >>= 28; while (d-- > 0) { buf.append('['); } if ((t & Frame.BASE_KIND) == Frame.OBJECT) { buf.append('L'); buf.append(cw.typeTable[t & Frame.BASE_VALUE].strVal1); buf.append(';'); } else { switch (t & 0xF) { case 1: buf.append('I'); break; case 2: buf.append('F'); break; case 3: buf.append('D'); break; case 9: buf.append('Z'); break; case 10: buf.append('B'); break; case 11: buf.append('C'); break; case 12: buf.append('S'); break; default: buf.append('J'); } } stackMap.putByte(7).putShort(cw.newClass(buf.toString())); } } } private void writeFrameType(final Object type) { if (type instanceof String) { stackMap.putByte(7).putShort(cw.newClass((String) type)); } else if (type instanceof Integer) { stackMap.putByte(((Integer) type).intValue()); } else { stackMap.putByte(8).putShort(((Label) type).position); } } // ------------------------------------------------------------------------ // Utility methods: dump bytecode array // ------------------------------------------------------------------------ /** * Returns the size of the bytecode of this method. * * @return the size of the bytecode of this method. */ final int getSize() { if (classReaderOffset != 0) { return 6 + classReaderLength; } if (resize) { // replaces the temporary jump opcodes introduced by Label.resolve. if (ClassReader.RESIZE) { resizeInstructions(); } else { throw new RuntimeException("Method code too large!"); } } int size = 8; if (code.length > 0) { if (code.length > 65536) { throw new RuntimeException("Method code too large!"); } cw.newUTF8("Code"); size += 18 + code.length + 8 * handlerCount; if (localVar != null) { cw.newUTF8("LocalVariableTable"); size += 8 + localVar.length; } if (localVarType != null) { cw.newUTF8("LocalVariableTypeTable"); size += 8 + localVarType.length; } if (lineNumber != null) { cw.newUTF8("LineNumberTable"); size += 8 + lineNumber.length; } if (stackMap != null) { boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6; cw.newUTF8(zip ? "StackMapTable" : "StackMap"); size += 8 + stackMap.length; } if (cattrs != null) { size += cattrs.getSize(cw, code.data, code.length, maxStack, maxLocals); } } if (exceptionCount > 0) { cw.newUTF8("Exceptions"); size += 8 + 2 * exceptionCount; } if ((access & Opcodes.ACC_SYNTHETIC) != 0) { if ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { cw.newUTF8("Synthetic"); size += 6; } } if ((access & Opcodes.ACC_DEPRECATED) != 0) { cw.newUTF8("Deprecated"); size += 6; } if (ClassReader.SIGNATURES && signature != null) { cw.newUTF8("Signature"); cw.newUTF8(signature); size += 8; } if (ClassReader.ANNOTATIONS && annd != null) { cw.newUTF8("AnnotationDefault"); size += 6 + annd.length; } if (ClassReader.ANNOTATIONS && anns != null) { cw.newUTF8("RuntimeVisibleAnnotations"); size += 8 + anns.getSize(); } if (ClassReader.ANNOTATIONS && ianns != null) { cw.newUTF8("RuntimeInvisibleAnnotations"); size += 8 + ianns.getSize(); } if (ClassReader.ANNOTATIONS && panns != null) { cw.newUTF8("RuntimeVisibleParameterAnnotations"); size += 7 + 2 * (panns.length - synthetics); for (int i = panns.length - 1; i >= synthetics; --i) { size += panns[i] == null ? 0 : panns[i].getSize(); } } if (ClassReader.ANNOTATIONS && ipanns != null) { cw.newUTF8("RuntimeInvisibleParameterAnnotations"); size += 7 + 2 * (ipanns.length - synthetics); for (int i = ipanns.length - 1; i >= synthetics; --i) { size += ipanns[i] == null ? 0 : ipanns[i].getSize(); } } if (attrs != null) { size += attrs.getSize(cw, null, 0, -1, -1); } return size; } /** * Puts the bytecode of this method in the given byte vector. * * @param out * the byte vector into which the bytecode of this method must be * copied. */ final void put(final ByteVector out) { final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC; int mask = ACC_CONSTRUCTOR | Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR); out.putShort(access & ~mask).putShort(name).putShort(desc); if (classReaderOffset != 0) { out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength); return; } int attributeCount = 0; if (code.length > 0) { ++attributeCount; } if (exceptionCount > 0) { ++attributeCount; } if ((access & Opcodes.ACC_SYNTHETIC) != 0) { if ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { ++attributeCount; } } if ((access & Opcodes.ACC_DEPRECATED) != 0) { ++attributeCount; } if (ClassReader.SIGNATURES && signature != null) { ++attributeCount; } if (ClassReader.ANNOTATIONS && annd != null) { ++attributeCount; } if (ClassReader.ANNOTATIONS && anns != null) { ++attributeCount; } if (ClassReader.ANNOTATIONS && ianns != null) { ++attributeCount; } if (ClassReader.ANNOTATIONS && panns != null) { ++attributeCount; } if (ClassReader.ANNOTATIONS && ipanns != null) { ++attributeCount; } if (attrs != null) { attributeCount += attrs.getCount(); } out.putShort(attributeCount); if (code.length > 0) { int size = 12 + code.length + 8 * handlerCount; if (localVar != null) { size += 8 + localVar.length; } if (localVarType != null) { size += 8 + localVarType.length; } if (lineNumber != null) { size += 8 + lineNumber.length; } if (stackMap != null) { size += 8 + stackMap.length; } if (cattrs != null) { size += cattrs.getSize(cw, code.data, code.length, maxStack, maxLocals); } out.putShort(cw.newUTF8("Code")).putInt(size); out.putShort(maxStack).putShort(maxLocals); out.putInt(code.length).putByteArray(code.data, 0, code.length); out.putShort(handlerCount); if (handlerCount > 0) { Handler h = firstHandler; while (h != null) { out.putShort(h.start.position).putShort(h.end.position) .putShort(h.handler.position).putShort(h.type); h = h.next; } } attributeCount = 0; if (localVar != null) { ++attributeCount; } if (localVarType != null) { ++attributeCount; } if (lineNumber != null) { ++attributeCount; } if (stackMap != null) { ++attributeCount; } if (cattrs != null) { attributeCount += cattrs.getCount(); } out.putShort(attributeCount); if (localVar != null) { out.putShort(cw.newUTF8("LocalVariableTable")); out.putInt(localVar.length + 2).putShort(localVarCount); out.putByteArray(localVar.data, 0, localVar.length); } if (localVarType != null) { out.putShort(cw.newUTF8("LocalVariableTypeTable")); out.putInt(localVarType.length + 2).putShort(localVarTypeCount); out.putByteArray(localVarType.data, 0, localVarType.length); } if (lineNumber != null) { out.putShort(cw.newUTF8("LineNumberTable")); out.putInt(lineNumber.length + 2).putShort(lineNumberCount); out.putByteArray(lineNumber.data, 0, lineNumber.length); } if (stackMap != null) { boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6; out.putShort(cw.newUTF8(zip ? "StackMapTable" : "StackMap")); out.putInt(stackMap.length + 2).putShort(frameCount); out.putByteArray(stackMap.data, 0, stackMap.length); } if (cattrs != null) { cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out); } } if (exceptionCount > 0) { out.putShort(cw.newUTF8("Exceptions")).putInt( 2 * exceptionCount + 2); out.putShort(exceptionCount); for (int i = 0; i < exceptionCount; ++i) { out.putShort(exceptions[i]); } } if ((access & Opcodes.ACC_SYNTHETIC) != 0) { if ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) { out.putShort(cw.newUTF8("Synthetic")).putInt(0); } } if ((access & Opcodes.ACC_DEPRECATED) != 0) { out.putShort(cw.newUTF8("Deprecated")).putInt(0); } if (ClassReader.SIGNATURES && signature != null) { out.putShort(cw.newUTF8("Signature")).putInt(2) .putShort(cw.newUTF8(signature)); } if (ClassReader.ANNOTATIONS && annd != null) { out.putShort(cw.newUTF8("AnnotationDefault")); out.putInt(annd.length); out.putByteArray(annd.data, 0, annd.length); } if (ClassReader.ANNOTATIONS && anns != null) { out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); anns.put(out); } if (ClassReader.ANNOTATIONS && ianns != null) { out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); ianns.put(out); } if (ClassReader.ANNOTATIONS && panns != null) { out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations")); AnnotationWriter.put(panns, synthetics, out); } if (ClassReader.ANNOTATIONS && ipanns != null) { out.putShort(cw.newUTF8("RuntimeInvisibleParameterAnnotations")); AnnotationWriter.put(ipanns, synthetics, out); } if (attrs != null) { attrs.put(cw, null, 0, -1, -1, out); } } // ------------------------------------------------------------------------ // Utility methods: instruction resizing (used to handle GOTO_W and JSR_W) // ------------------------------------------------------------------------ /** * Resizes and replaces the temporary instructions inserted by * {@link Label#resolve} for wide forward jumps, while keeping jump offsets * and instruction addresses consistent. This may require to resize other * existing instructions, or even to introduce new instructions: for * example, increasing the size of an instruction by 2 at the middle of a * method can increases the offset of an IFEQ instruction from 32766 to * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W * 32765. This, in turn, may require to increase the size of another jump * instruction, and so on... All these operations are handled automatically * by this method. *

* This method must be called after all the method that is being built * has been visited. In particular, the {@link Label Label} objects used * to construct the method are no longer valid after this method has been * called. */ private void resizeInstructions() { byte[] b = code.data; // bytecode of the method int u, v, label; // indexes in b int i, j; // loop indexes /* * 1st step: As explained above, resizing an instruction may require to * resize another one, which may require to resize yet another one, and * so on. The first step of the algorithm consists in finding all the * instructions that need to be resized, without modifying the code. * This is done by the following "fix point" algorithm: * * Parse the code to find the jump instructions whose offset will need * more than 2 bytes to be stored (the future offset is computed from * the current offset and from the number of bytes that will be inserted * or removed between the source and target instructions). For each such * instruction, adds an entry in (a copy of) the indexes and sizes * arrays (if this has not already been done in a previous iteration!). * * If at least one entry has been added during the previous step, go * back to the beginning, otherwise stop. * * In fact the real algorithm is complicated by the fact that the size * of TABLESWITCH and LOOKUPSWITCH instructions depends on their * position in the bytecode (because of padding). In order to ensure the * convergence of the algorithm, the number of bytes to be added or * removed from these instructions is over estimated during the previous * loop, and computed exactly only after the loop is finished (this * requires another pass to parse the bytecode of the method). */ int[] allIndexes = new int[0]; // copy of indexes int[] allSizes = new int[0]; // copy of sizes boolean[] resize; // instructions to be resized int newOffset; // future offset of a jump instruction resize = new boolean[code.length]; // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done int state = 3; do { if (state == 3) { state = 2; } u = 0; while (u < b.length) { int opcode = b[u] & 0xFF; // opcode of current instruction int insert = 0; // bytes to be added after this instruction switch (ClassWriter.TYPE[opcode]) { case ClassWriter.NOARG_INSN: case ClassWriter.IMPLVAR_INSN: u += 1; break; case ClassWriter.LABEL_INSN: if (opcode > 201) { // converts temporary opcodes 202 to 217, 218 and // 219 to IFEQ ... JSR (inclusive), IFNULL and // IFNONNULL opcode = opcode < 218 ? opcode - 49 : opcode - 20; label = u + readUnsignedShort(b, u + 1); } else { label = u + readShort(b, u + 1); } newOffset = getNewOffset(allIndexes, allSizes, u, label); if (newOffset < Short.MIN_VALUE || newOffset > Short.MAX_VALUE) { if (!resize[u]) { if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) { // two additional bytes will be required to // replace this GOTO or JSR instruction with // a GOTO_W or a JSR_W insert = 2; } else { // five additional bytes will be required to // replace this IFxxx instruction with // IFNOTxxx GOTO_W , where IFNOTxxx // is the "opposite" opcode of IFxxx (i.e., // IFNE for IFEQ) and where designates // the instruction just after the GOTO_W. insert = 5; } resize[u] = true; } } u += 3; break; case ClassWriter.LABELW_INSN: u += 5; break; case ClassWriter.TABL_INSN: if (state == 1) { // true number of bytes to be added (or removed) // from this instruction = (future number of padding // bytes - current number of padding byte) - // previously over estimated variation = // = ((3 - newOffset%4) - (3 - u%4)) - u%4 // = (-newOffset%4 + u%4) - u%4 // = -(newOffset & 3) newOffset = getNewOffset(allIndexes, allSizes, 0, u); insert = -(newOffset & 3); } else if (!resize[u]) { // over estimation of the number of bytes to be // added to this instruction = 3 - current number // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3 insert = u & 3; resize[u] = true; } // skips instruction u = u + 4 - (u & 3); u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12; break; case ClassWriter.LOOK_INSN: if (state == 1) { // like TABL_INSN newOffset = getNewOffset(allIndexes, allSizes, 0, u); insert = -(newOffset & 3); } else if (!resize[u]) { // like TABL_INSN insert = u & 3; resize[u] = true; } // skips instruction u = u + 4 - (u & 3); u += 8 * readInt(b, u + 4) + 8; break; case ClassWriter.WIDE_INSN: opcode = b[u + 1] & 0xFF; if (opcode == Opcodes.IINC) { u += 6; } else { u += 4; } break; case ClassWriter.VAR_INSN: case ClassWriter.SBYTE_INSN: case ClassWriter.LDC_INSN: u += 2; break; case ClassWriter.SHORT_INSN: case ClassWriter.LDCW_INSN: case ClassWriter.FIELDORMETH_INSN: case ClassWriter.TYPE_INSN: case ClassWriter.IINC_INSN: u += 3; break; case ClassWriter.ITFMETH_INSN: case ClassWriter.INDYMETH_INSN: u += 5; break; // case ClassWriter.MANA_INSN: default: u += 4; break; } if (insert != 0) { // adds a new (u, insert) entry in the allIndexes and // allSizes arrays int[] newIndexes = new int[allIndexes.length + 1]; int[] newSizes = new int[allSizes.length + 1]; System.arraycopy(allIndexes, 0, newIndexes, 0, allIndexes.length); System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length); newIndexes[allIndexes.length] = u; newSizes[allSizes.length] = insert; allIndexes = newIndexes; allSizes = newSizes; if (insert > 0) { state = 3; } } } if (state < 3) { --state; } } while (state != 0); // 2nd step: // copies the bytecode of the method into a new bytevector, updates the // offsets, and inserts (or removes) bytes as requested. ByteVector newCode = new ByteVector(code.length); u = 0; while (u < code.length) { int opcode = b[u] & 0xFF; switch (ClassWriter.TYPE[opcode]) { case ClassWriter.NOARG_INSN: case ClassWriter.IMPLVAR_INSN: newCode.putByte(opcode); u += 1; break; case ClassWriter.LABEL_INSN: if (opcode > 201) { // changes temporary opcodes 202 to 217 (inclusive), 218 // and 219 to IFEQ ... JSR (inclusive), IFNULL and // IFNONNULL opcode = opcode < 218 ? opcode - 49 : opcode - 20; label = u + readUnsignedShort(b, u + 1); } else { label = u + readShort(b, u + 1); } newOffset = getNewOffset(allIndexes, allSizes, u, label); if (resize[u]) { // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx // with IFNOTxxx GOTO_W , where IFNOTxxx is // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) // and where designates the instruction just after // the GOTO_W. if (opcode == Opcodes.GOTO) { newCode.putByte(200); // GOTO_W } else if (opcode == Opcodes.JSR) { newCode.putByte(201); // JSR_W } else { newCode.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1); newCode.putShort(8); // jump offset newCode.putByte(200); // GOTO_W // newOffset now computed from start of GOTO_W newOffset -= 3; } newCode.putInt(newOffset); } else { newCode.putByte(opcode); newCode.putShort(newOffset); } u += 3; break; case ClassWriter.LABELW_INSN: label = u + readInt(b, u + 1); newOffset = getNewOffset(allIndexes, allSizes, u, label); newCode.putByte(opcode); newCode.putInt(newOffset); u += 5; break; case ClassWriter.TABL_INSN: // skips 0 to 3 padding bytes v = u; u = u + 4 - (v & 3); // reads and copies instruction newCode.putByte(Opcodes.TABLESWITCH); newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4); label = v + readInt(b, u); u += 4; newOffset = getNewOffset(allIndexes, allSizes, v, label); newCode.putInt(newOffset); j = readInt(b, u); u += 4; newCode.putInt(j); j = readInt(b, u) - j + 1; u += 4; newCode.putInt(readInt(b, u - 4)); for (; j > 0; --j) { label = v + readInt(b, u); u += 4; newOffset = getNewOffset(allIndexes, allSizes, v, label); newCode.putInt(newOffset); } break; case ClassWriter.LOOK_INSN: // skips 0 to 3 padding bytes v = u; u = u + 4 - (v & 3); // reads and copies instruction newCode.putByte(Opcodes.LOOKUPSWITCH); newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4); label = v + readInt(b, u); u += 4; newOffset = getNewOffset(allIndexes, allSizes, v, label); newCode.putInt(newOffset); j = readInt(b, u); u += 4; newCode.putInt(j); for (; j > 0; --j) { newCode.putInt(readInt(b, u)); u += 4; label = v + readInt(b, u); u += 4; newOffset = getNewOffset(allIndexes, allSizes, v, label); newCode.putInt(newOffset); } break; case ClassWriter.WIDE_INSN: opcode = b[u + 1] & 0xFF; if (opcode == Opcodes.IINC) { newCode.putByteArray(b, u, 6); u += 6; } else { newCode.putByteArray(b, u, 4); u += 4; } break; case ClassWriter.VAR_INSN: case ClassWriter.SBYTE_INSN: case ClassWriter.LDC_INSN: newCode.putByteArray(b, u, 2); u += 2; break; case ClassWriter.SHORT_INSN: case ClassWriter.LDCW_INSN: case ClassWriter.FIELDORMETH_INSN: case ClassWriter.TYPE_INSN: case ClassWriter.IINC_INSN: newCode.putByteArray(b, u, 3); u += 3; break; case ClassWriter.ITFMETH_INSN: case ClassWriter.INDYMETH_INSN: newCode.putByteArray(b, u, 5); u += 5; break; // case MANA_INSN: default: newCode.putByteArray(b, u, 4); u += 4; break; } } // recomputes the stack map frames if (frameCount > 0) { if (compute == FRAMES) { frameCount = 0; stackMap = null; previousFrame = null; frame = null; Frame f = new Frame(); f.owner = labels; Type[] args = Type.getArgumentTypes(descriptor); f.initInputFrame(cw, access, args, maxLocals); visitFrame(f); Label l = labels; while (l != null) { /* * here we need the original label position. getNewOffset * must therefore never have been called for this label. */ u = l.position - 3; if ((l.status & Label.STORE) != 0 || (u >= 0 && resize[u])) { getNewOffset(allIndexes, allSizes, l); // TODO update offsets in UNINITIALIZED values visitFrame(l.frame); } l = l.successor; } } else { /* * Resizing an existing stack map frame table is really hard. * Not only the table must be parsed to update the offets, but * new frames may be needed for jump instructions that were * inserted by this method. And updating the offsets or * inserting frames can change the format of the following * frames, in case of packed frames. In practice the whole table * must be recomputed. For this the frames are marked as * potentially invalid. This will cause the whole class to be * reread and rewritten with the COMPUTE_FRAMES option (see the * ClassWriter.toByteArray method). This is not very efficient * but is much easier and requires much less code than any other * method I can think of. */ cw.invalidFrames = true; } } // updates the exception handler block labels Handler h = firstHandler; while (h != null) { getNewOffset(allIndexes, allSizes, h.start); getNewOffset(allIndexes, allSizes, h.end); getNewOffset(allIndexes, allSizes, h.handler); h = h.next; } // updates the instructions addresses in the // local var and line number tables for (i = 0; i < 2; ++i) { ByteVector bv = i == 0 ? localVar : localVarType; if (bv != null) { b = bv.data; u = 0; while (u < bv.length) { label = readUnsignedShort(b, u); newOffset = getNewOffset(allIndexes, allSizes, 0, label); writeShort(b, u, newOffset); label += readUnsignedShort(b, u + 2); newOffset = getNewOffset(allIndexes, allSizes, 0, label) - newOffset; writeShort(b, u + 2, newOffset); u += 10; } } } if (lineNumber != null) { b = lineNumber.data; u = 0; while (u < lineNumber.length) { writeShort( b, u, getNewOffset(allIndexes, allSizes, 0, readUnsignedShort(b, u))); u += 4; } } // updates the labels of the other attributes Attribute attr = cattrs; while (attr != null) { Label[] labels = attr.getLabels(); if (labels != null) { for (i = labels.length - 1; i >= 0; --i) { getNewOffset(allIndexes, allSizes, labels[i]); } } attr = attr.next; } // replaces old bytecodes with new ones code = newCode; } /** * Reads an unsigned short value in the given byte array. * * @param b * a byte array. * @param index * the start index of the value to be read. * @return the read value. */ static int readUnsignedShort(final byte[] b, final int index) { return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); } /** * Reads a signed short value in the given byte array. * * @param b * a byte array. * @param index * the start index of the value to be read. * @return the read value. */ static short readShort(final byte[] b, final int index) { return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); } /** * Reads a signed int value in the given byte array. * * @param b * a byte array. * @param index * the start index of the value to be read. * @return the read value. */ static int readInt(final byte[] b, final int index) { return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF); } /** * Writes a short value in the given byte array. * * @param b * a byte array. * @param index * where the first byte of the short value must be written. * @param s * the value to be written in the given byte array. */ static void writeShort(final byte[] b, final int index, final int s) { b[index] = (byte) (s >>> 8); b[index + 1] = (byte) s; } /** * Computes the future value of a bytecode offset. *

* Note: it is possible to have several entries for the same instruction in * the indexes and sizes: two entries (index=a,size=b) and * (index=a,size=b') are equivalent to a single entry (index=a,size=b+b'). * * @param indexes * current positions of the instructions to be resized. Each * instruction must be designated by the index of its last * byte, plus one (or, in other words, by the index of the * first byte of the next instruction). * @param sizes * the number of bytes to be added to the above * instructions. More precisely, for each i < len, * sizes[i] bytes will be added at the end of the * instruction designated by indexes[i] or, if * sizes[i] is negative, the last | * sizes[i]| bytes of the instruction will be removed * (the instruction size must not become negative or * null). * @param begin * index of the first byte of the source instruction. * @param end * index of the first byte of the target instruction. * @return the future value of the given bytecode offset. */ static int getNewOffset(final int[] indexes, final int[] sizes, final int begin, final int end) { int offset = end - begin; for (int i = 0; i < indexes.length; ++i) { if (begin < indexes[i] && indexes[i] <= end) { // forward jump offset += sizes[i]; } else if (end < indexes[i] && indexes[i] <= begin) { // backward jump offset -= sizes[i]; } } return offset; } /** * Updates the offset of the given label. * * @param indexes * current positions of the instructions to be resized. Each * instruction must be designated by the index of its last * byte, plus one (or, in other words, by the index of the * first byte of the next instruction). * @param sizes * the number of bytes to be added to the above * instructions. More precisely, for each i < len, * sizes[i] bytes will be added at the end of the * instruction designated by indexes[i] or, if * sizes[i] is negative, the last | * sizes[i]| bytes of the instruction will be removed * (the instruction size must not become negative or * null). * @param label * the label whose offset must be updated. */ static void getNewOffset(final int[] indexes, final int[] sizes, final Label label) { if ((label.status & Label.RESIZED) == 0) { label.position = getNewOffset(indexes, sizes, 0, label.position); label.status |= Label.RESIZED; } } } libasm4-java-4.1/src/org/objectweb/asm/Opcodes.java000066400000000000000000000255511207310427500222020ustar00rootroot00000000000000/*** * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.objectweb.asm; /** * Defines the JVM opcodes, access flags and array type codes. This interface * does not define all the JVM opcodes because some opcodes are automatically * handled. For example, the xLOAD and xSTORE opcodes are automatically replaced * by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n * opcodes are therefore not defined in this interface. Likewise for LDC, * automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and * JSR_W. * * @author Eric Bruneton * @author Eugene Kuleshov */ public interface Opcodes { // ASM API versions int ASM4 = 4 << 16 | 0 << 8 | 0; // versions int V1_1 = 3 << 16 | 45; int V1_2 = 0 << 16 | 46; int V1_3 = 0 << 16 | 47; int V1_4 = 0 << 16 | 48; int V1_5 = 0 << 16 | 49; int V1_6 = 0 << 16 | 50; int V1_7 = 0 << 16 | 51; // access flags int ACC_PUBLIC = 0x0001; // class, field, method int ACC_PRIVATE = 0x0002; // class, field, method int ACC_PROTECTED = 0x0004; // class, field, method int ACC_STATIC = 0x0008; // field, method int ACC_FINAL = 0x0010; // class, field, method int ACC_SUPER = 0x0020; // class int ACC_SYNCHRONIZED = 0x0020; // method int ACC_VOLATILE = 0x0040; // field int ACC_BRIDGE = 0x0040; // method int ACC_VARARGS = 0x0080; // method int ACC_TRANSIENT = 0x0080; // field int ACC_NATIVE = 0x0100; // method int ACC_INTERFACE = 0x0200; // class int ACC_ABSTRACT = 0x0400; // class, method int ACC_STRICT = 0x0800; // method int ACC_SYNTHETIC = 0x1000; // class, field, method int ACC_ANNOTATION = 0x2000; // class int ACC_ENUM = 0x4000; // class(?) field inner // ASM specific pseudo access flags int ACC_DEPRECATED = 0x20000; // class, field, method // types for NEWARRAY int T_BOOLEAN = 4; int T_CHAR = 5; int T_FLOAT = 6; int T_DOUBLE = 7; int T_BYTE = 8; int T_SHORT = 9; int T_INT = 10; int T_LONG = 11; // tags for Handle int H_GETFIELD = 1; int H_GETSTATIC = 2; int H_PUTFIELD = 3; int H_PUTSTATIC = 4; int H_INVOKEVIRTUAL = 5; int H_INVOKESTATIC = 6; int H_INVOKESPECIAL = 7; int H_NEWINVOKESPECIAL = 8; int H_INVOKEINTERFACE = 9; // stack map frame types /** * Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}. */ int F_NEW = -1; /** * Represents a compressed frame with complete frame data. */ int F_FULL = 0; /** * Represents a compressed frame where locals are the same as the locals in * the previous frame, except that additional 1-3 locals are defined, and * with an empty stack. */ int F_APPEND = 1; /** * Represents a compressed frame where locals are the same as the locals in * the previous frame, except that the last 1-3 locals are absent and with * an empty stack. */ int F_CHOP = 2; /** * Represents a compressed frame with exactly the same locals as the * previous frame and with an empty stack. */ int F_SAME = 3; /** * Represents a compressed frame with exactly the same locals as the * previous frame and with a single value on the stack. */ int F_SAME1 = 4; Integer TOP = new Integer(0); Integer INTEGER = new Integer(1); Integer FLOAT = new Integer(2); Integer DOUBLE = new Integer(3); Integer LONG = new Integer(4); Integer NULL = new Integer(5); Integer UNINITIALIZED_THIS = new Integer(6); // opcodes // visit method (- = idem) int NOP = 0; // visitInsn int ACONST_NULL = 1; // - int ICONST_M1 = 2; // - int ICONST_0 = 3; // - int ICONST_1 = 4; // - int ICONST_2 = 5; // - int ICONST_3 = 6; // - int ICONST_4 = 7; // - int ICONST_5 = 8; // - int LCONST_0 = 9; // - int LCONST_1 = 10; // - int FCONST_0 = 11; // - int FCONST_1 = 12; // - int FCONST_2 = 13; // - int DCONST_0 = 14; // - int DCONST_1 = 15; // - int BIPUSH = 16; // visitIntInsn int SIPUSH = 17; // - int LDC = 18; // visitLdcInsn // int LDC_W = 19; // - // int LDC2_W = 20; // - int ILOAD = 21; // visitVarInsn int LLOAD = 22; // - int FLOAD = 23; // - int DLOAD = 24; // - int ALOAD = 25; // - // int ILOAD_0 = 26; // - // int ILOAD_1 = 27; // - // int ILOAD_2 = 28; // - // int ILOAD_3 = 29; // - // int LLOAD_0 = 30; // - // int LLOAD_1 = 31; // - // int LLOAD_2 = 32; // - // int LLOAD_3 = 33; // - // int FLOAD_0 = 34; // - // int FLOAD_1 = 35; // - // int FLOAD_2 = 36; // - // int FLOAD_3 = 37; // - // int DLOAD_0 = 38; // - // int DLOAD_1 = 39; // - // int DLOAD_2 = 40; // - // int DLOAD_3 = 41; // - // int ALOAD_0 = 42; // - // int ALOAD_1 = 43; // - // int ALOAD_2 = 44; // - // int ALOAD_3 = 45; // - int IALOAD = 46; // visitInsn int LALOAD = 47; // - int FALOAD = 48; // - int DALOAD = 49; // - int AALOAD = 50; // - int BALOAD = 51; // - int CALOAD = 52; // - int SALOAD = 53; // - int ISTORE = 54; // visitVarInsn int LSTORE = 55; // - int FSTORE = 56; // - int DSTORE = 57; // - int ASTORE = 58; // - // int ISTORE_0 = 59; // - // int ISTORE_1 = 60; // - // int ISTORE_2 = 61; // - // int ISTORE_3 = 62; // - // int LSTORE_0 = 63; // - // int LSTORE_1 = 64; // - // int LSTORE_2 = 65; // - // int LSTORE_3 = 66; // - // int FSTORE_0 = 67; // - // int FSTORE_1 = 68; // - // int FSTORE_2 = 69; // - // int FSTORE_3 = 70; // - // int DSTORE_0 = 71; // - // int DSTORE_1 = 72; // - // int DSTORE_2 = 73; // - // int DSTORE_3 = 74; // - // int ASTORE_0 = 75; // - // int ASTORE_1 = 76; // - // int ASTORE_2 = 77; // - // int ASTORE_3 = 78; // - int IASTORE = 79; // visitInsn int LASTORE = 80; // - int FASTORE = 81; // - int DASTORE = 82; // - int AASTORE = 83; // - int BASTORE = 84; // - int CASTORE = 85; // - int SASTORE = 86; // - int POP = 87; // - int POP2 = 88; // - int DUP = 89; // - int DUP_X1 = 90; // - int DUP_X2 = 91; // - int DUP2 = 92; // - int DUP2_X1 = 93; // - int DUP2_X2 = 94; // - int SWAP = 95; // - int IADD = 96; // - int LADD = 97; // - int FADD = 98; // - int DADD = 99; // - int ISUB = 100; // - int LSUB = 101; // - int FSUB = 102; // - int DSUB = 103; // - int IMUL = 104; // - int LMUL = 105; // - int FMUL = 106; // - int DMUL = 107; // - int IDIV = 108; // - int LDIV = 109; // - int FDIV = 110; // - int DDIV = 111; // - int IREM = 112; // - int LREM = 113; // - int FREM = 114; // - int DREM = 115; // - int INEG = 116; // - int LNEG = 117; // - int FNEG = 118; // - int DNEG = 119; // - int ISHL = 120; // - int LSHL = 121; // - int ISHR = 122; // - int LSHR = 123; // - int IUSHR = 124; // - int LUSHR = 125; // - int IAND = 126; // - int LAND = 127; // - int IOR = 128; // - int LOR = 129; // - int IXOR = 130; // - int LXOR = 131; // - int IINC = 132; // visitIincInsn int I2L = 133; // visitInsn int I2F = 134; // - int I2D = 135; // - int L2I = 136; // - int L2F = 137; // - int L2D = 138; // - int F2I = 139; // - int F2L = 140; // - int F2D = 141; // - int D2I = 142; // - int D2L = 143; // - int D2F = 144; // - int I2B = 145; // - int I2C = 146; // - int I2S = 147; // - int LCMP = 148; // - int FCMPL = 149; // - int FCMPG = 150; // - int DCMPL = 151; // - int DCMPG = 152; // - int IFEQ = 153; // visitJumpInsn int IFNE = 154; // - int IFLT = 155; // - int IFGE = 156; // - int IFGT = 157; // - int IFLE = 158; // - int IF_ICMPEQ = 159; // - int IF_ICMPNE = 160; // - int IF_ICMPLT = 161; // - int IF_ICMPGE = 162; // - int IF_ICMPGT = 163; // - int IF_ICMPLE = 164; // - int IF_ACMPEQ = 165; // - int IF_ACMPNE = 166; // - int GOTO = 167; // - int JSR = 168; // - int RET = 169; // visitVarInsn int TABLESWITCH = 170; // visiTableSwitchInsn int LOOKUPSWITCH = 171; // visitLookupSwitch int IRETURN = 172; // visitInsn int LRETURN = 173; // - int FRETURN = 174; // - int DRETURN = 175; // - int ARETURN = 176; // - int RETURN = 177; // - int GETSTATIC = 178; // visitFieldInsn int PUTSTATIC = 179; // - int GETFIELD = 180; // - int PUTFIELD = 181; // - int INVOKEVIRTUAL = 182; // visitMethodInsn int INVOKESPECIAL = 183; // - int INVOKESTATIC = 184; // - int INVOKEINTERFACE = 185; // - int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsn int NEW = 187; // visitTypeInsn int NEWARRAY = 188; // visitIntInsn int ANEWARRAY = 189; // visitTypeInsn int ARRAYLENGTH = 190; // visitInsn int ATHROW = 191; // - int CHECKCAST = 192; // visitTypeInsn int INSTANCEOF = 193; // - int MONITORENTER = 194; // visitInsn int MONITOREXIT = 195; // - // int WIDE = 196; // NOT VISITED int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn int IFNULL = 198; // visitJumpInsn int IFNONNULL = 199; // - // int GOTO_W = 200; // - // int JSR_W = 201; // - } libasm4-java-4.1/src/org/objectweb/asm/Type.java000066400000000000000000000711751207310427500215320ustar00rootroot00000000000000/*** * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.objectweb.asm; import java.lang.reflect.Constructor; import java.lang.reflect.Method; /** * A Java field or method type. This class can be used to make it easier to * manipulate type and method descriptors. * * @author Eric Bruneton * @author Chris Nokleberg */ public class Type { /** * The sort of the void type. See {@link #getSort getSort}. */ public static final int VOID = 0; /** * The sort of the boolean type. See {@link #getSort getSort}. */ public static final int BOOLEAN = 1; /** * The sort of the char type. See {@link #getSort getSort}. */ public static final int CHAR = 2; /** * The sort of the byte type. See {@link #getSort getSort}. */ public static final int BYTE = 3; /** * The sort of the short type. See {@link #getSort getSort}. */ public static final int SHORT = 4; /** * The sort of the int type. See {@link #getSort getSort}. */ public static final int INT = 5; /** * The sort of the float type. See {@link #getSort getSort}. */ public static final int FLOAT = 6; /** * The sort of the long type. See {@link #getSort getSort}. */ public static final int LONG = 7; /** * The sort of the double type. See {@link #getSort getSort}. */ public static final int DOUBLE = 8; /** * The sort of array reference types. See {@link #getSort getSort}. */ public static final int ARRAY = 9; /** * The sort of object reference types. See {@link #getSort getSort}. */ public static final int OBJECT = 10; /** * The sort of method types. See {@link #getSort getSort}. */ public static final int METHOD = 11; /** * The void type. */ public static final Type VOID_TYPE = new Type(VOID, null, ('V' << 24) | (5 << 16) | (0 << 8) | 0, 1); /** * The boolean type. */ public static final Type BOOLEAN_TYPE = new Type(BOOLEAN, null, ('Z' << 24) | (0 << 16) | (5 << 8) | 1, 1); /** * The char type. */ public static final Type CHAR_TYPE = new Type(CHAR, null, ('C' << 24) | (0 << 16) | (6 << 8) | 1, 1); /** * The byte type. */ public static final Type BYTE_TYPE = new Type(BYTE, null, ('B' << 24) | (0 << 16) | (5 << 8) | 1, 1); /** * The short type. */ public static final Type SHORT_TYPE = new Type(SHORT, null, ('S' << 24) | (0 << 16) | (7 << 8) | 1, 1); /** * The int type. */ public static final Type INT_TYPE = new Type(INT, null, ('I' << 24) | (0 << 16) | (0 << 8) | 1, 1); /** * The float type. */ public static final Type FLOAT_TYPE = new Type(FLOAT, null, ('F' << 24) | (2 << 16) | (2 << 8) | 1, 1); /** * The long type. */ public static final Type LONG_TYPE = new Type(LONG, null, ('J' << 24) | (1 << 16) | (1 << 8) | 2, 1); /** * The double type. */ public static final Type DOUBLE_TYPE = new Type(DOUBLE, null, ('D' << 24) | (3 << 16) | (3 << 8) | 2, 1); // ------------------------------------------------------------------------ // Fields // ------------------------------------------------------------------------ /** * The sort of this Java type. */ private final int sort; /** * A buffer containing the internal name of this Java type. This field is * only used for reference types. */ private final char[] buf; /** * The offset of the internal name of this Java type in {@link #buf buf} or, * for primitive types, the size, descriptor and getOpcode offsets for this * type (byte 0 contains the size, byte 1 the descriptor, byte 2 the offset * for IALOAD or IASTORE, byte 3 the offset for all other instructions). */ private final int off; /** * The length of the internal name of this Java type. */ private final int len; // ------------------------------------------------------------------------ // Constructors // ------------------------------------------------------------------------ /** * Constructs a reference type. * * @param sort * the sort of the reference type to be constructed. * @param buf * a buffer containing the descriptor of the previous type. * @param off * the offset of this descriptor in the previous buffer. * @param len * the length of this descriptor. */ private Type(final int sort, final char[] buf, final int off, final int len) { this.sort = sort; this.buf = buf; this.off = off; this.len = len; } /** * Returns the Java type corresponding to the given type descriptor. * * @param typeDescriptor * a field or method type descriptor. * @return the Java type corresponding to the given type descriptor. */ public static Type getType(final String typeDescriptor) { return getType(typeDescriptor.toCharArray(), 0); } /** * Returns the Java type corresponding to the given internal name. * * @param internalName * an internal name. * @return the Java type corresponding to the given internal name. */ public static Type getObjectType(final String internalName) { char[] buf = internalName.toCharArray(); return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length); } /** * Returns the Java type corresponding to the given method descriptor. * Equivalent to Type.getType(methodDescriptor). * * @param methodDescriptor * a method descriptor. * @return the Java type corresponding to the given method descriptor. */ public static Type getMethodType(final String methodDescriptor) { return getType(methodDescriptor.toCharArray(), 0); } /** * Returns the Java method type corresponding to the given argument and * return types. * * @param returnType * the return type of the method. * @param argumentTypes * the argument types of the method. * @return the Java type corresponding to the given argument and return * types. */ public static Type getMethodType(final Type returnType, final Type... argumentTypes) { return getType(getMethodDescriptor(returnType, argumentTypes)); } /** * Returns the Java type corresponding to the given class. * * @param c * a class. * @return the Java type corresponding to the given class. */ public static Type getType(final Class c) { if (c.isPrimitive()) { if (c == Integer.TYPE) { return INT_TYPE; } else if (c == Void.TYPE) { return VOID_TYPE; } else if (c == Boolean.TYPE) { return BOOLEAN_TYPE; } else if (c == Byte.TYPE) { return BYTE_TYPE; } else if (c == Character.TYPE) { return CHAR_TYPE; } else if (c == Short.TYPE) { return SHORT_TYPE; } else if (c == Double.TYPE) { return DOUBLE_TYPE; } else if (c == Float.TYPE) { return FLOAT_TYPE; } else /* if (c == Long.TYPE) */{ return LONG_TYPE; } } else { return getType(getDescriptor(c)); } } /** * Returns the Java method type corresponding to the given constructor. * * @param c * a {@link Constructor Constructor} object. * @return the Java method type corresponding to the given constructor. */ public static Type getType(final Constructor c) { return getType(getConstructorDescriptor(c)); } /** * Returns the Java method type corresponding to the given method. * * @param m * a {@link Method Method} object. * @return the Java method type corresponding to the given method. */ public static Type getType(final Method m) { return getType(getMethodDescriptor(m)); } /** * Returns the Java types corresponding to the argument types of the given * method descriptor. * * @param methodDescriptor * a method descriptor. * @return the Java types corresponding to the argument types of the given * method descriptor. */ public static Type[] getArgumentTypes(final String methodDescriptor) { char[] buf = methodDescriptor.toCharArray(); int off = 1; int size = 0; while (true) { char car = buf[off++]; if (car == ')') { break; } else if (car == 'L') { while (buf[off++] != ';') { } ++size; } else if (car != '[') { ++size; } } Type[] args = new Type[size]; off = 1; size = 0; while (buf[off] != ')') { args[size] = getType(buf, off); off += args[size].len + (args[size].sort == OBJECT ? 2 : 0); size += 1; } return args; } /** * Returns the Java types corresponding to the argument types of the given * method. * * @param method * a method. * @return the Java types corresponding to the argument types of the given * method. */ public static Type[] getArgumentTypes(final Method method) { Class[] classes = method.getParameterTypes(); Type[] types = new Type[classes.length]; for (int i = classes.length - 1; i >= 0; --i) { types[i] = getType(classes[i]); } return types; } /** * Returns the Java type corresponding to the return type of the given * method descriptor. * * @param methodDescriptor * a method descriptor. * @return the Java type corresponding to the return type of the given * method descriptor. */ public static Type getReturnType(final String methodDescriptor) { char[] buf = methodDescriptor.toCharArray(); return getType(buf, methodDescriptor.indexOf(')') + 1); } /** * Returns the Java type corresponding to the return type of the given * method. * * @param method * a method. * @return the Java type corresponding to the return type of the given * method. */ public static Type getReturnType(final Method method) { return getType(method.getReturnType()); } /** * Computes the size of the arguments and of the return value of a method. * * @param desc * the descriptor of a method. * @return the size of the arguments of the method (plus one for the * implicit this argument), argSize, and the size of its return * value, retSize, packed into a single int i = * (argSize << 2) | retSize (argSize is therefore equal to * i >> 2, and retSize to i & 0x03). */ public static int getArgumentsAndReturnSizes(final String desc) { int n = 1; int c = 1; while (true) { char car = desc.charAt(c++); if (car == ')') { car = desc.charAt(c); return n << 2 | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1)); } else if (car == 'L') { while (desc.charAt(c++) != ';') { } n += 1; } else if (car == '[') { while ((car = desc.charAt(c)) == '[') { ++c; } if (car == 'D' || car == 'J') { n -= 1; } } else if (car == 'D' || car == 'J') { n += 2; } else { n += 1; } } } /** * Returns the Java type corresponding to the given type descriptor. For * method descriptors, buf is supposed to contain nothing more than the * descriptor itself. * * @param buf * a buffer containing a type descriptor. * @param off * the offset of this descriptor in the previous buffer. * @return the Java type corresponding to the given type descriptor. */ private static Type getType(final char[] buf, final int off) { int len; switch (buf[off]) { case 'V': return VOID_TYPE; case 'Z': return BOOLEAN_TYPE; case 'C': return CHAR_TYPE; case 'B': return BYTE_TYPE; case 'S': return SHORT_TYPE; case 'I': return INT_TYPE; case 'F': return FLOAT_TYPE; case 'J': return LONG_TYPE; case 'D': return DOUBLE_TYPE; case '[': len = 1; while (buf[off + len] == '[') { ++len; } if (buf[off + len] == 'L') { ++len; while (buf[off + len] != ';') { ++len; } } return new Type(ARRAY, buf, off, len + 1); case 'L': len = 1; while (buf[off + len] != ';') { ++len; } return new Type(OBJECT, buf, off + 1, len - 1); // case '(': default: return new Type(METHOD, buf, off, buf.length - off); } } // ------------------------------------------------------------------------ // Accessors // ------------------------------------------------------------------------ /** * Returns the sort of this Java type. * * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR}, * {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT}, * {@link #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE}, * {@link #ARRAY ARRAY}, {@link #OBJECT OBJECT} or {@link #METHOD * METHOD}. */ public int getSort() { return sort; } /** * Returns the number of dimensions of this array type. This method should * only be used for an array type. * * @return the number of dimensions of this array type. */ public int getDimensions() { int i = 1; while (buf[off + i] == '[') { ++i; } return i; } /** * Returns the type of the elements of this array type. This method should * only be used for an array type. * * @return Returns the type of the elements of this array type. */ public Type getElementType() { return getType(buf, off + getDimensions()); } /** * Returns the binary name of the class corresponding to this type. This * method must not be used on method types. * * @return the binary name of the class corresponding to this type. */ public String getClassName() { switch (sort) { case VOID: return "void"; case BOOLEAN: return "boolean"; case CHAR: return "char"; case BYTE: return "byte"; case SHORT: return "short"; case INT: return "int"; case FLOAT: return "float"; case LONG: return "long"; case DOUBLE: return "double"; case ARRAY: StringBuffer b = new StringBuffer(getElementType().getClassName()); for (int i = getDimensions(); i > 0; --i) { b.append("[]"); } return b.toString(); case OBJECT: return new String(buf, off, len).replace('/', '.'); default: return null; } } /** * Returns the internal name of the class corresponding to this object or * array type. The internal name of a class is its fully qualified name (as * returned by Class.getName(), where '.' are replaced by '/'. This method * should only be used for an object or array type. * * @return the internal name of the class corresponding to this object type. */ public String getInternalName() { return new String(buf, off, len); } /** * Returns the argument types of methods of this type. This method should * only be used for method types. * * @return the argument types of methods of this type. */ public Type[] getArgumentTypes() { return getArgumentTypes(getDescriptor()); } /** * Returns the return type of methods of this type. This method should only * be used for method types. * * @return the return type of methods of this type. */ public Type getReturnType() { return getReturnType(getDescriptor()); } /** * Returns the size of the arguments and of the return value of methods of * this type. This method should only be used for method types. * * @return the size of the arguments (plus one for the implicit this * argument), argSize, and the size of the return value, retSize, * packed into a single int i = (argSize << 2) | retSize * (argSize is therefore equal to i >> 2, and retSize to * i & 0x03). */ public int getArgumentsAndReturnSizes() { return getArgumentsAndReturnSizes(getDescriptor()); } // ------------------------------------------------------------------------ // Conversion to type descriptors // ------------------------------------------------------------------------ /** * Returns the descriptor corresponding to this Java type. * * @return the descriptor corresponding to this Java type. */ public String getDescriptor() { StringBuffer buf = new StringBuffer(); getDescriptor(buf); return buf.toString(); } /** * Returns the descriptor corresponding to the given argument and return * types. * * @param returnType * the return type of the method. * @param argumentTypes * the argument types of the method. * @return the descriptor corresponding to the given argument and return * types. */ public static String getMethodDescriptor(final Type returnType, final Type... argumentTypes) { StringBuffer buf = new StringBuffer(); buf.append('('); for (int i = 0; i < argumentTypes.length; ++i) { argumentTypes[i].getDescriptor(buf); } buf.append(')'); returnType.getDescriptor(buf); return buf.toString(); } /** * Appends the descriptor corresponding to this Java type to the given * string buffer. * * @param buf * the string buffer to which the descriptor must be appended. */ private void getDescriptor(final StringBuffer buf) { if (this.buf == null) { // descriptor is in byte 3 of 'off' for primitive types (buf == // null) buf.append((char) ((off & 0xFF000000) >>> 24)); } else if (sort == OBJECT) { buf.append('L'); buf.append(this.buf, off, len); buf.append(';'); } else { // sort == ARRAY || sort == METHOD buf.append(this.buf, off, len); } } // ------------------------------------------------------------------------ // Direct conversion from classes to type descriptors, // without intermediate Type objects // ------------------------------------------------------------------------ /** * Returns the internal name of the given class. The internal name of a * class is its fully qualified name, as returned by Class.getName(), where * '.' are replaced by '/'. * * @param c * an object or array class. * @return the internal name of the given class. */ public static String getInternalName(final Class c) { return c.getName().replace('.', '/'); } /** * Returns the descriptor corresponding to the given Java type. * * @param c * an object class, a primitive class or an array class. * @return the descriptor corresponding to the given class. */ public static String getDescriptor(final Class c) { StringBuffer buf = new StringBuffer(); getDescriptor(buf, c); return buf.toString(); } /** * Returns the descriptor corresponding to the given constructor. * * @param c * a {@link Constructor Constructor} object. * @return the descriptor of the given constructor. */ public static String getConstructorDescriptor(final Constructor c) { Class[] parameters = c.getParameterTypes(); StringBuffer buf = new StringBuffer(); buf.append('('); for (int i = 0; i < parameters.length; ++i) { getDescriptor(buf, parameters[i]); } return buf.append(")V").toString(); } /** * Returns the descriptor corresponding to the given method. * * @param m * a {@link Method Method} object. * @return the descriptor of the given method. */ public static String getMethodDescriptor(final Method m) { Class[] parameters = m.getParameterTypes(); StringBuffer buf = new StringBuffer(); buf.append('('); for (int i = 0; i < parameters.length; ++i) { getDescriptor(buf, parameters[i]); } buf.append(')'); getDescriptor(buf, m.getReturnType()); return buf.toString(); } /** * Appends the descriptor of the given class to the given string buffer. * * @param buf * the string buffer to which the descriptor must be appended. * @param c * the class whose descriptor must be computed. */ private static void getDescriptor(final StringBuffer buf, final Class c) { Class d = c; while (true) { if (d.isPrimitive()) { char car; if (d == Integer.TYPE) { car = 'I'; } else if (d == Void.TYPE) { car = 'V'; } else if (d == Boolean.TYPE) { car = 'Z'; } else if (d == Byte.TYPE) { car = 'B'; } else if (d == Character.TYPE) { car = 'C'; } else if (d == Short.TYPE) { car = 'S'; } else if (d == Double.TYPE) { car = 'D'; } else if (d == Float.TYPE) { car = 'F'; } else /* if (d == Long.TYPE) */{ car = 'J'; } buf.append(car); return; } else if (d.isArray()) { buf.append('['); d = d.getComponentType(); } else { buf.append('L'); String name = d.getName(); int len = name.length(); for (int i = 0; i < len; ++i) { char car = name.charAt(i); buf.append(car == '.' ? '/' : car); } buf.append(';'); return; } } } // ------------------------------------------------------------------------ // Corresponding size and opcodes // ------------------------------------------------------------------------ /** * Returns the size of values of this type. This method must not be used for * method types. * * @return the size of values of this type, i.e., 2 for long and * double, 0 for void and 1 otherwise. */ public int getSize() { // the size is in byte 0 of 'off' for primitive types (buf == null) return buf == null ? (off & 0xFF) : 1; } /** * Returns a JVM instruction opcode adapted to this Java type. This method * must not be used for method types. * * @param opcode * a JVM instruction opcode. This opcode must be one of ILOAD, * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, * ISHL, ISHR, IUSHR, IAND, IOR, IXOR and IRETURN. * @return an opcode that is similar to the given opcode, but adapted to * this Java type. For example, if this type is float and * opcode is IRETURN, this method returns FRETURN. */ public int getOpcode(final int opcode) { if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) { // the offset for IALOAD or IASTORE is in byte 1 of 'off' for // primitive types (buf == null) return opcode + (buf == null ? (off & 0xFF00) >> 8 : 4); } else { // the offset for other instructions is in byte 2 of 'off' for // primitive types (buf == null) return opcode + (buf == null ? (off & 0xFF0000) >> 16 : 4); } } // ------------------------------------------------------------------------ // Equals, hashCode and toString // ------------------------------------------------------------------------ /** * Tests if the given object is equal to this type. * * @param o * the object to be compared to this type. * @return true if the given object is equal to this type. */ @Override public boolean equals(final Object o) { if (this == o) { return true; } if (!(o instanceof Type)) { return false; } Type t = (Type) o; if (sort != t.sort) { return false; } if (sort >= ARRAY) { if (len != t.len) { return false; } for (int i = off, j = t.off, end = i + len; i < end; i++, j++) { if (buf[i] != t.buf[j]) { return false; } } } return true; } /** * Returns a hash code value for this type. * * @return a hash code value for this type. */ @Override public int hashCode() { int hc = 13 * sort; if (sort >= ARRAY) { for (int i = off, end = i + len; i < end; i++) { hc = 17 * (hc + buf[i]); } } return hc; } /** * Returns a string representation of this type. * * @return the descriptor of this type. */ @Override public String toString() { return getDescriptor(); } } libasm4-java-4.1/src/org/objectweb/asm/attrs/000077500000000000000000000000001207310427500210705ustar00rootroot00000000000000libasm4-java-4.1/src/org/objectweb/asm/attrs/package.html000066400000000000000000000046441207310427500233610ustar00rootroot00000000000000 Provides an implementation for optional class, field and method attributes.

By default ASM strips optional attributes, in order to keep them in the bytecode that is being readed you should pass an array of required attribute instances to {@link org.objectweb.asm.ClassReader#accept(org.objectweb.asm.ClassVisitor, org.objectweb.asm.Attribute[], boolean) ClassReader.accept()} method. In order to add custom attributes to the manually constructed bytecode concrete subclasses of the {@link org.objectweb.asm.Attribute Attribute} can be passed to the visitAttribute methods of the {@link org.objectweb.asm.ClassVisitor ClassVisitor}, {@link org.objectweb.asm.FieldVisitor FieldVisitor} and {@link org.objectweb.asm.MethodVisitor MethodVisitor} interfaces. @since ASM 1.4.1 libasm4-java-4.1/src/org/objectweb/asm/commons/000077500000000000000000000000001207310427500214065ustar00rootroot00000000000000libasm4-java-4.1/src/org/objectweb/asm/commons/AdviceAdapter.java000066400000000000000000000453101207310427500247500ustar00rootroot00000000000000/*** * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.objectweb.asm.commons; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.objectweb.asm.Handle; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; /** * A {@link org.objectweb.asm.MethodVisitor} to insert before, after and around * advices in methods and constructors. *

* The behavior for constructors is like this: *

    * *
  1. as long as the INVOKESPECIAL for the object initialization has not been * reached, every bytecode instruction is dispatched in the ctor code visitor
  2. * *
  3. when this one is reached, it is only added in the ctor code visitor and a * JP invoke is added
  4. * *
  5. after that, only the other code visitor receives the instructions
  6. * *
* * @author Eugene Kuleshov * @author Eric Bruneton */ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes { private static final Object THIS = new Object(); private static final Object OTHER = new Object(); protected int methodAccess; protected String methodDesc; private boolean constructor; private boolean superInitialized; private List stackFrame; private Map> branches; /** * Creates a new {@link AdviceAdapter}. * * @param api * the ASM API version implemented by this visitor. Must be one * of {@link Opcodes#ASM4}. * @param mv * the method visitor to which this adapter delegates calls. * @param access * the method's access flags (see {@link Opcodes}). * @param name * the method's name. * @param desc * the method's descriptor (see {@link Type Type}). */ protected AdviceAdapter(final int api, final MethodVisitor mv, final int access, final String name, final String desc) { super(api, mv, access, name, desc); methodAccess = access; methodDesc = desc; constructor = "".equals(name); } @Override public void visitCode() { mv.visitCode(); if (constructor) { stackFrame = new ArrayList(); branches = new HashMap>(); } else { superInitialized = true; onMethodEnter(); } } @Override public void visitLabel(final Label label) { mv.visitLabel(label); if (constructor && branches != null) { List frame = branches.get(label); if (frame != null) { stackFrame = frame; branches.remove(label); } } } @Override public void visitInsn(final int opcode) { if (constructor) { int s; switch (opcode) { case RETURN: // empty stack onMethodExit(opcode); break; case IRETURN: // 1 before n/a after case FRETURN: // 1 before n/a after case ARETURN: // 1 before n/a after case ATHROW: // 1 before n/a after popValue(); onMethodExit(opcode); break; case LRETURN: // 2 before n/a after case DRETURN: // 2 before n/a after popValue(); popValue(); onMethodExit(opcode); break; case NOP: case LALOAD: // remove 2 add 2 case DALOAD: // remove 2 add 2 case LNEG: case DNEG: case FNEG: case INEG: case L2D: case D2L: case F2I: case I2B: case I2C: case I2S: case I2F: case ARRAYLENGTH: break; case ACONST_NULL: case ICONST_M1: case ICONST_0: case ICONST_1: case ICONST_2: case ICONST_3: case ICONST_4: case ICONST_5: case FCONST_0: case FCONST_1: case FCONST_2: case F2L: // 1 before 2 after case F2D: case I2L: case I2D: pushValue(OTHER); break; case LCONST_0: case LCONST_1: case DCONST_0: case DCONST_1: pushValue(OTHER); pushValue(OTHER); break; case IALOAD: // remove 2 add 1 case FALOAD: // remove 2 add 1 case AALOAD: // remove 2 add 1 case BALOAD: // remove 2 add 1 case CALOAD: // remove 2 add 1 case SALOAD: // remove 2 add 1 case POP: case IADD: case FADD: case ISUB: case LSHL: // 3 before 2 after case LSHR: // 3 before 2 after case LUSHR: // 3 before 2 after case L2I: // 2 before 1 after case L2F: // 2 before 1 after case D2I: // 2 before 1 after case D2F: // 2 before 1 after case FSUB: case FMUL: case FDIV: case FREM: case FCMPL: // 2 before 1 after case FCMPG: // 2 before 1 after case IMUL: case IDIV: case IREM: case ISHL: case ISHR: case IUSHR: case IAND: case IOR: case IXOR: case MONITORENTER: case MONITOREXIT: popValue(); break; case POP2: case LSUB: case LMUL: case LDIV: case LREM: case LADD: case LAND: case LOR: case LXOR: case DADD: case DMUL: case DSUB: case DDIV: case DREM: popValue(); popValue(); break; case IASTORE: case FASTORE: case AASTORE: case BASTORE: case CASTORE: case SASTORE: case LCMP: // 4 before 1 after case DCMPL: case DCMPG: popValue(); popValue(); popValue(); break; case LASTORE: case DASTORE: popValue(); popValue(); popValue(); popValue(); break; case DUP: pushValue(peekValue()); break; case DUP_X1: s = stackFrame.size(); stackFrame.add(s - 2, stackFrame.get(s - 1)); break; case DUP_X2: s = stackFrame.size(); stackFrame.add(s - 3, stackFrame.get(s - 1)); break; case DUP2: s = stackFrame.size(); stackFrame.add(s - 2, stackFrame.get(s - 1)); stackFrame.add(s - 2, stackFrame.get(s - 1)); break; case DUP2_X1: s = stackFrame.size(); stackFrame.add(s - 3, stackFrame.get(s - 1)); stackFrame.add(s - 3, stackFrame.get(s - 1)); break; case DUP2_X2: s = stackFrame.size(); stackFrame.add(s - 4, stackFrame.get(s - 1)); stackFrame.add(s - 4, stackFrame.get(s - 1)); break; case SWAP: s = stackFrame.size(); stackFrame.add(s - 2, stackFrame.get(s - 1)); stackFrame.remove(s); break; } } else { switch (opcode) { case RETURN: case IRETURN: case FRETURN: case ARETURN: case LRETURN: case DRETURN: case ATHROW: onMethodExit(opcode); break; } } mv.visitInsn(opcode); } @Override public void visitVarInsn(final int opcode, final int var) { super.visitVarInsn(opcode, var); if (constructor) { switch (opcode) { case ILOAD: case FLOAD: pushValue(OTHER); break; case LLOAD: case DLOAD: pushValue(OTHER); pushValue(OTHER); break; case ALOAD: pushValue(var == 0 ? THIS : OTHER); break; case ASTORE: case ISTORE: case FSTORE: popValue(); break; case LSTORE: case DSTORE: popValue(); popValue(); break; } } } @Override public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) { mv.visitFieldInsn(opcode, owner, name, desc); if (constructor) { char c = desc.charAt(0); boolean longOrDouble = c == 'J' || c == 'D'; switch (opcode) { case GETSTATIC: pushValue(OTHER); if (longOrDouble) { pushValue(OTHER); } break; case PUTSTATIC: popValue(); if (longOrDouble) { popValue(); } break; case PUTFIELD: popValue(); if (longOrDouble) { popValue(); popValue(); } break; // case GETFIELD: default: if (longOrDouble) { pushValue(OTHER); } } } } @Override public void visitIntInsn(final int opcode, final int operand) { mv.visitIntInsn(opcode, operand); if (constructor && opcode != NEWARRAY) { pushValue(OTHER); } } @Override public void visitLdcInsn(final Object cst) { mv.visitLdcInsn(cst); if (constructor) { pushValue(OTHER); if (cst instanceof Double || cst instanceof Long) { pushValue(OTHER); } } } @Override public void visitMultiANewArrayInsn(final String desc, final int dims) { mv.visitMultiANewArrayInsn(desc, dims); if (constructor) { for (int i = 0; i < dims; i++) { popValue(); } pushValue(OTHER); } } @Override public void visitTypeInsn(final int opcode, final String type) { mv.visitTypeInsn(opcode, type); // ANEWARRAY, CHECKCAST or INSTANCEOF don't change stack if (constructor && opcode == NEW) { pushValue(OTHER); } } @Override public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) { mv.visitMethodInsn(opcode, owner, name, desc); if (constructor) { Type[] types = Type.getArgumentTypes(desc); for (int i = 0; i < types.length; i++) { popValue(); if (types[i].getSize() == 2) { popValue(); } } switch (opcode) { // case INVOKESTATIC: // break; case INVOKEINTERFACE: case INVOKEVIRTUAL: popValue(); // objectref break; case INVOKESPECIAL: Object type = popValue(); // objectref if (type == THIS && !superInitialized) { onMethodEnter(); superInitialized = true; // once super has been initialized it is no longer // necessary to keep track of stack state constructor = false; } break; } Type returnType = Type.getReturnType(desc); if (returnType != Type.VOID_TYPE) { pushValue(OTHER); if (returnType.getSize() == 2) { pushValue(OTHER); } } } } @Override public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); if (constructor) { Type[] types = Type.getArgumentTypes(desc); for (int i = 0; i < types.length; i++) { popValue(); if (types[i].getSize() == 2) { popValue(); } } Type returnType = Type.getReturnType(desc); if (returnType != Type.VOID_TYPE) { pushValue(OTHER); if (returnType.getSize() == 2) { pushValue(OTHER); } } } } @Override public void visitJumpInsn(final int opcode, final Label label) { mv.visitJumpInsn(opcode, label); if (constructor) { switch (opcode) { case IFEQ: case IFNE: case IFLT: case IFGE: case IFGT: case IFLE: case IFNULL: case IFNONNULL: popValue(); break; case IF_ICMPEQ: case IF_ICMPNE: case IF_ICMPLT: case IF_ICMPGE: case IF_ICMPGT: case IF_ICMPLE: case IF_ACMPEQ: case IF_ACMPNE: popValue(); popValue(); break; case JSR: pushValue(OTHER); break; } addBranch(label); } } @Override public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) { mv.visitLookupSwitchInsn(dflt, keys, labels); if (constructor) { popValue(); addBranches(dflt, labels); } } @Override public void visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label... labels) { mv.visitTableSwitchInsn(min, max, dflt, labels); if (constructor) { popValue(); addBranches(dflt, labels); } } @Override public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { super.visitTryCatchBlock(start, end, handler, type); if (constructor && !branches.containsKey(handler)) { List stackFrame = new ArrayList(); stackFrame.add(OTHER); branches.put(handler, stackFrame); } } private void addBranches(final Label dflt, final Label[] labels) { addBranch(dflt); for (int i = 0; i < labels.length; i++) { addBranch(labels[i]); } } private void addBranch(final Label label) { if (branches.containsKey(label)) { return; } branches.put(label, new ArrayList(stackFrame)); } private Object popValue() { return stackFrame.remove(stackFrame.size() - 1); } private Object peekValue() { return stackFrame.get(stackFrame.size() - 1); } private void pushValue(final Object o) { stackFrame.add(o); } /** * Called at the beginning of the method or after super class class call in * the constructor.
*
* * Custom code can use or change all the local variables, but should not * change state of the stack. */ protected void onMethodEnter() { } /** * Called before explicit exit from the method using either return or throw. * Top element on the stack contains the return value or exception instance. * For example: * *
     *   public void onMethodExit(int opcode) {
     *     if(opcode==RETURN) {
     *         visitInsn(ACONST_NULL);
     *     } else if(opcode==ARETURN || opcode==ATHROW) {
     *         dup();
     *     } else {
     *         if(opcode==LRETURN || opcode==DRETURN) {
     *             dup2();
     *         } else {
     *             dup();
     *         }
     *         box(Type.getReturnType(this.methodDesc));
     *     }
     *     visitIntInsn(SIPUSH, opcode);
     *     visitMethodInsn(INVOKESTATIC, owner, "onExit", "(Ljava/lang/Object;I)V");
     *   }
     * 
     *   // an actual call back method
     *   public static void onExit(Object param, int opcode) {
     *     ...
     * 
* *
*
* * Custom code can use or change all the local variables, but should not * change state of the stack. * * @param opcode * one of the RETURN, IRETURN, FRETURN, ARETURN, LRETURN, DRETURN * or ATHROW * */ protected void onMethodExit(int opcode) { } // TODO onException, onMethodCall } libasm4-java-4.1/src/org/objectweb/asm/commons/AnalyzerAdapter.java000066400000000000000000000675531207310427500253570ustar00rootroot00000000000000/*** * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2011 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.objectweb.asm.commons; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.objectweb.asm.Handle; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; /** * A {@link MethodVisitor} that keeps track of stack map frame changes between * {@link #visitFrame(int, int, Object[], int, Object[]) visitFrame} calls. This * adapter must be used with the * {@link org.objectweb.asm.ClassReader#EXPAND_FRAMES} option. Each * visitX instruction delegates to the next visitor in the chain, if any, * and then simulates the effect of this instruction on the stack map frame, * represented by {@link #locals} and {@link #stack}. The next visitor in the * chain can get the state of the stack map frame before each instruction * by reading the value of these fields in its visitX methods (this * requires a reference to the AnalyzerAdapter that is before it in the chain). * If this adapter is used with a class that does not contain stack map table * attributes (i.e., pre Java 6 classes) then this adapter may not be able to * compute the stack map frame for each instruction. In this case no exception * is thrown but the {@link #locals} and {@link #stack} fields will be null for * these instructions. * * @author Eric Bruneton */ public class AnalyzerAdapter extends MethodVisitor { /** * List of the local variable slots for current execution * frame. Primitive types are represented by {@link Opcodes#TOP}, * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by * two elements, the second one being TOP). Reference types are represented * by String objects (representing internal names), and uninitialized types * by Label objects (this label designates the NEW instruction that created * this uninitialized value). This field is null for unreachable * instructions. */ public List locals; /** * List of the operand stack slots for current execution frame. * Primitive types are represented by {@link Opcodes#TOP}, * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by * two elements, the second one being TOP). Reference types are represented * by String objects (representing internal names), and uninitialized types * by Label objects (this label designates the NEW instruction that created * this uninitialized value). This field is null for unreachable * instructions. */ public List stack; /** * The labels that designate the next instruction to be visited. May be * null. */ private List