Comments (11)
看代码发现 ClassNotFoundExceptione 是 ReflectiveOperationException 的子类,于是修改如下
@TargetApi(Build.VERSION_CODES.KITKAT)
private static String getWakeLockTag(PowerManager.WakeLock wakeLock) {
String tag = "Default-WakeLock-Tag";
if (wakeLock == null) {
return tag;
}
try {
Method getTagMethod = wakeLock.getClass().getDeclaredMethod("getTag");
getTagMethod.setAccessible(true);
tag = (String) getTagMethod.invoke(wakeLock, (Object[]) null);
} catch (ReflectiveOperationException e) {
LogUtil.w(TAG,e);
} catch (Exception e) {
LogUtil.w(TAG,e);
}
return tag;
}
查看手机系统为Android4.2.2.r1源码:
有wakeLock 这个内部类,但是没有getTag这个方法。
且来看看高版本的方法:
/** @hide */
public void setTag(String tag) {
mTag = tag;
}
/** @hide */
public String getTag() {
return mTag;
}
可以看出加了 @hide 对外不公开,但是系统内部可见的,所以这里要用反射。
from androidbox.
以为万事大吉,谁知道报了
java.lang.VerifyError: com/xxx/xxx/xxx/xxx/manager/WakeLockManager
getWakeLockTag 是上述类WakeLockManager中的一个方法
查资料说是JVM加载类的时候,“校验器”检查文件格式虽然正确,但是内部的存在不一致性和安全性的问题,所以抛出了该错误。
不同的虚拟编译器不一样,所以抛出的错误信息叶铿不一样。
异常名称 异常栈中的段落信息 可能原因
-
java.lang.VerifyError Call to wrong initialization method 可能是在调用构造函数即的时候传进了错误的owner
-
java.lang.VerifyError Incompatible object argument for function call 同样是方法调用的时候出现的错误。看时候有参数设置错误了
-
java.lang.VerifyError Stack size too large 设置的最大栈空间大小不够
-
java.lang.VerifyError Illegal local variable number 可能是设置的最大局部变量大小不够,也可能是访问的局部变量的index不对
-
java.lang.VerifyError Must call initializers using invokespecial 在你调用 方法的时候使用了非INVOKESPECIAL的其他操纵码了。
-
java.lang.VerifyError Expecting to find integer on stack 可能是在赋值的时候类型不匹配,典型的就是将int类型直接赋值到Integer这之类的。固然在写java代码的时候可以直接赋值,但是在字节码的时候先要调用Integer的valueOf方法创建一个Integer对象再赋值
-
java.lang.ClassFormatError Arguments can't fit into locals in class file 可能是设置的最大局部变量大小不够
Android 虚拟机注意
ART 模式下面,可能不会报告错误
但是在 Davlik 虚拟机下,会在运行时编译,检测器就会工作
导致在5.0及其以上的设备工作正常,但在操作系统5.0以下(部分4.4开启了ART不会出现)以下报告java.lang.VerifyError` 错误
导致这个错误的原因有2个
三方jar包本身有错误
反编译smali代码修改继承或者申请寄存器操作错误
作者:泛原罪
链接:https://www.jianshu.com/p/07873b237b86
from androidbox.
看完上述的文章,还是没搞明白为什么会有这个错误
接着看到另外一篇文章
Android 不想和你说话,抛了个 java.lang.VerifyError
文中说明出现这个异常的问题主要在类文件校验错误,出现这种情况的情况有:
- 去extends 一个final类,去override一个final方法等
- 使用的方法高版本的SDK有但是低版本没有
但是,这个地方既然已经用了反射的,为什么还会报这个错误?
from androidbox.
怀疑修改后还是存在版本兼容性问题
于是删除方法的注解
@TargetApi(Build.VERSION_CODES.KITKAT)
果然,发现编译器警告ReflectiveOperationException
这么说,是这个ReflectiveOperationException在低版本中JVM加载时存在错误,理论上说的通。
from androidbox.
查看了Android的API文档
马上就发现,这个ReflectiveOperationException在19之后才加入,所以我们添加了注解:
@TargetApi(Build.VERSION_CODES.KITKAT)
那么,加了该注解,我们应该对低版本进行下兼容处理。
@TargetApi(Build.VERSION_CODES.KITKAT)
private static String getWakeLockTag(PowerManager.WakeLock wakeLock,String wakeLockName) {
String tag = "Default-WakeLock-Tag";
if (wakeLock == null) {
return tag;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
Method getTagMethod = wakeLock.getClass().getDeclaredMethod("getTag");
getTagMethod.setAccessible(true);
tag = (String) getTagMethod.invoke(wakeLock, (Object[]) null);
} catch (ReflectiveOperationException e) {
LogUtil.w(TAG,e);
} catch (Exception e) {
LogUtil.w(TAG,e);
}
}else {
LogUtil.d(TAG, "api < 19 ,so wakeLockName: " + wakeLockName);
return wakeLockName;
}
return tag;
}
from androidbox.
经过验证,还是报了如下相同异常
AndroidRuntime: FATAL EXCEPTION: Thread-21891
java.lang.VerifyError: com/xxx/xxx/xxx/xxx/xxx/WakeLockManager
at com.xxx.xxx.xxx.xxx.b.b.b(Unknown Source)
at com.xxx.xxx.xxx.xxx.b.b.a(Unknown Source)
at com.xxx.xxx.xxx.xxx.b.b$1.run(Unknown Source)
如果在5.0.0的机器上跑,则不存在该问题。
from androidbox.
如图,注释掉该部分代码就正常了
实际只需要将ReflectiveOperationException的变成Exception也不会有问题。
捕获的异常:java.lang.NoSuchMethodException: getTag []
基本说明了是运行时加载Class存在问题。
from androidbox.
查看这个class的文件,发现如下:
Constant pool:
#63 = Class #191 // java/lang/ReflectiveOperationException
#117 = Utf8 Ljava/lang/ReflectiveOperationException;
#119 = Class #191 // java/lang/ReflectiveOperationException
#191 = Utf8 java/lang/ReflectiveOperationException
from androidbox.
查JVM虚拟机类加载机制中验证步骤,发现:
- 常量池的常量中是否有不被支持的常量类型(检查常量tag标志)
ReflectiveOperationException这个就是在低版本Android系统中不被支持的,所以在低版本Android系统中加载该WakeLockManager类时就报:java.lang.VerifyError。
from androidbox.
上述的说法并不完全正确,因为发现如果我们修改代码如下:
private static String getWakeLockTag(PowerManager.WakeLock wakeLock,String wakeLockName) {
String tag = "Default-WakeLock-Tag";
if (wakeLock == null) {
return tag;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
Method getTagMethod = wakeLock.getClass().getDeclaredMethod("getTag");
getTagMethod.setAccessible(true);
new ReflectiveOperationException("test");// 直接New一个,而不是在catch的代码块里面
tag = (String) getTagMethod.invoke(wakeLock, (Object[]) null);
}catch (Exception e) {
LogUtil.w(TAG,e);
}
}else {
LogUtil.d(TAG, "api < 19 ,so wakeLockName: " + wakeLockName);
return wakeLockName;
}
return tag;
}
这样在运行时,并不会报错。
from androidbox.
那么catch里面和直接在代码里面直接去new有什么区别呢?
- catch代码块在类加载时就会进行校验
- 而try方法代码中需要运行时才会检测
所以,出现了上述的现象。在代码中 new ReflectiveOperationException("test");并没有真正的运行,但是在catch代码块中直接就爆出了
java.lang.VerifyError`。
from androidbox.
Related Issues (20)
- Toast Show的时候出现 BadTokenException: Unable to add window -- token
- java.lang.IllegalStateException: Fragment already added HOT 2
- ANR: "main" prio=5 tid=1 WaitingForGcToComplete HOT 2
- Exception: The specified message queue synchronization barrier token has not been posted or has already been removed.
- ExceptionInInitializerError HOT 2
- 为什么Receiver不允许进行BindService
- Fragment生命周期
- SQLite多线程问题 HOT 3
- 《Android应用性能优化》 HOT 1
- 内存优化 HOT 1
- Native闪退 HOT 1
- java.lang.IllegalStateException: The specified child already has a parent.
- RxJava线程 HOT 1
- Service启动成功onCreate和onStartCmmand都不回调
- CursorWindowAllocationException HOT 1
- SharedPreferences解析
- Component class com.huawei.hms.support.api.push.PushEventReceiver does not exist in com.xtc.watch HOT 2
- SQLite查询操作源码分析:从 IllegalArgumentException:the bind value at index 2 is null 说起
- startActivityForResult的坑
- java.lang.IllegalArgumentException: pointerIndex out of range HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from androidbox.