- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
TL;DR:给定字节码,我如何找出给定方法中使用了哪些类和哪些方法?
在我的代码中,我想以编程方式 找到所有具有过多访问限定符的类和方法。这应该基于对继承的分析、静态使用以及我提供的提示(例如,使用一些自制注释,如 @KeepPublic
)来完成。作为一种特殊情况,将找到未使用的类和方法。
我只是做了一些类似但更简单的事情,即将 final
关键字添加到所有有意义的类(即,它是允许的,并且该类不会被 Hibernate 等代理)。我以测试的形式做到了这一点,它知道要忽略的类(例如,实体)并提示所有不必要的非最终类。
对于我的所有类,我想找到它使用的所有方法和类。关于类(class),有 this answer using ASM's Remapper .关于方法,我找到了an answer proposing instrumentation ,这不是我现在想要的。我也不是在寻找像 ucdetector 这样的工具它与 Eclipse AST 一起工作。 我如何根据字节码检查方法体?我想自己做,这样我就可以通过编程消除不需要的警告(在使用 Lombok 时,ucdetector 会出现很多警告)。
最佳答案
在每个方法的基础上查看用法,即通过分析所有指令,有一些缺陷。除了 method invocations 之外,可能还有方法引用,它将使用 invokedynamic
instruction 进行编码,在其 bsm
参数中有一个指向目标方法的 handle。如果字节码不是从普通 Java 代码生成的(或源自 future 版本),您必须准备好可能遇到 ldc
instructions 指向 handle,这将在运行时产生 MethodHandle
。
既然你已经提到了“继承分析”,我只想指出极端情况,即for
package foo;
class A {
public void method() {}
}
class B implements bar.If {
}
package bar;
public interface If {
void method();
}
很容易忽略 A.method()
必须保持 public
。
如果您保持保守,即当您无法确定 B
实例是否最终会成为其他地方的 If.method()
调用的目标时在您的应用程序中,您必须假设这是可能的,您不会发现太多需要优化的地方。我认为您至少需要桥接方法的内联和合成的内部/外部类访问器来识别继承关系中未使用的成员。
当涉及到类引用时,确实有更多的可能性使每条指令的分析容易出错。它们不仅可以作为成员访问指令的所有者出现,还可以用于 new
、checkcast
、instanceof
和数组特定指令、注释、异常处理程序更糟糕的是,signatures 可能出现在成员引用、注释、局部变量调试提示等处。ldc
指令可能引用类,生成 Class
实例,在普通Java代码中实际使用,例如对于类文字,但如前所述,理论上也有可能生成 MethodHandle
,它可能引用所有者类,但也有带有参数类型和返回类型的签名,或者生成 MethodType
代表一个签名。
你最好分析常量池,然而,ASM 不提供。准确地说,ClassReader
具有访问池的方法,但它们实际上并不打算由客户端代码使用(如其文档所述)。即使在那里,你也必须意识到陷阱。基本上,如果 CONSTANT_Utf8_info
对应,则 CONSTANT_Class_info
的内容带有类或签名引用。 CONSTANT_NameAndType_info
或 CONSTANT_MethodType_info
的描述符索引指向它。但是,类的声明成员直接引用 CONSTANT_Utf8_info
池条目来描述它们的签名,请参见 Methods 和 Fields 。同样,注释不遵循该模式并直接引用池的 CONSTANT_Utf8_info
条目,为其分配类型或签名语义,请参见 enum_const_value 和 class_info_index ......
关于java - 降低类和方法的可见性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43727089/
我想了解 Ruby 方法 methods() 是如何工作的。 我尝试使用“ruby 方法”在 Google 上搜索,但这不是我需要的。 我也看过 ruby-doc.org,但我没有找到这种方法。
Test 方法 对指定的字符串执行一个正则表达式搜索,并返回一个 Boolean 值指示是否找到匹配的模式。 object.Test(string) 参数 object 必选项。总是一个
Replace 方法 替换在正则表达式查找中找到的文本。 object.Replace(string1, string2) 参数 object 必选项。总是一个 RegExp 对象的名称。
Raise 方法 生成运行时错误 object.Raise(number, source, description, helpfile, helpcontext) 参数 object 应为
Execute 方法 对指定的字符串执行正则表达式搜索。 object.Execute(string) 参数 object 必选项。总是一个 RegExp 对象的名称。 string
Clear 方法 清除 Err 对象的所有属性设置。 object.Clear object 应为 Err 对象的名称。 说明 在错误处理后,使用 Clear 显式地清除 Err 对象。此
CopyFile 方法 将一个或多个文件从某位置复制到另一位置。 object.CopyFile source, destination[, overwrite] 参数 object 必选
Copy 方法 将指定的文件或文件夹从某位置复制到另一位置。 object.Copy destination[, overwrite] 参数 object 必选项。应为 File 或 F
Close 方法 关闭打开的 TextStream 文件。 object.Close object 应为 TextStream 对象的名称。 说明 下面例子举例说明如何使用 Close 方
BuildPath 方法 向现有路径后添加名称。 object.BuildPath(path, name) 参数 object 必选项。应为 FileSystemObject 对象的名称
GetFolder 方法 返回与指定的路径中某文件夹相应的 Folder 对象。 object.GetFolder(folderspec) 参数 object 必选项。应为 FileSy
GetFileName 方法 返回指定路径(不是指定驱动器路径部分)的最后一个文件或文件夹。 object.GetFileName(pathspec) 参数 object 必选项。应为
GetFile 方法 返回与指定路径中某文件相应的 File 对象。 object.GetFile(filespec) 参数 object 必选项。应为 FileSystemObject
GetExtensionName 方法 返回字符串,该字符串包含路径最后一个组成部分的扩展名。 object.GetExtensionName(path) 参数 object 必选项。应
GetDriveName 方法 返回包含指定路径中驱动器名的字符串。 object.GetDriveName(path) 参数 object 必选项。应为 FileSystemObjec
GetDrive 方法 返回与指定的路径中驱动器相对应的 Drive 对象。 object.GetDrive drivespec 参数 object 必选项。应为 FileSystemO
GetBaseName 方法 返回字符串,其中包含文件的基本名 (不带扩展名), 或者提供的路径说明中的文件夹。 object.GetBaseName(path) 参数 object 必
GetAbsolutePathName 方法 从提供的指定路径中返回完整且含义明确的路径。 object.GetAbsolutePathName(pathspec) 参数 object
FolderExists 方法 如果指定的文件夹存在,则返回 True;否则返回 False。 object.FolderExists(folderspec) 参数 object 必选项
FileExists 方法 如果指定的文件存在返回 True;否则返回 False。 object.FileExists(filespec) 参数 object 必选项。应为 FileS
我是一名优秀的程序员,十分优秀!