在阅读和扫描旧代码时,我看到了以下几行代码:
public static void replaceNull(Object obj)
{
if (obj == null)
{
return;
}
Field[] fields = obj.getClass().getDeclaredFields();
if (fields != null)
{
for (Field field : fields)
{
field.setAccessible(true);
Class<?> fieldType = field.getType();
try
{
if (field.get(obj) == null)
{
setDefaultValue(obj, field, fieldType);
}
} catch (IllegalArgumentException e)
{
logger. error("failed replacing null :"+ e.getMessage(),e);
} catch (IllegalAccessException e)
{
logger. error("failed replacing null :"+ e.getMessage(),e);
}
}
}
}
private static void setDefaultValue(Object obj, Field field, Class<?> fieldType) throws IllegalAccessException
{
if (fieldType == String.class)
{
field.set(obj, CommonConstants.BLANK);
} else if (fieldType == Date.class)
{
field.set(obj, new Date());
} else if (fieldType == Long.class)
{
field.setLong(obj, 0L);
} else if (fieldType == Integer.class)
{
field.setInt(obj, 0);
} else if (fieldType == BigDecimal.class)
{
field.set(obj, new BigDecimal("0.0"));
}
}
从程序流程中,如果值为null,编写器似乎想要为对象的所有数据成员创建默认值。
使用FindBugs进行扫描时,findbugs在setAccessible(true)上报告了“DP_DO_INSIDE_DO_PRIVILEGED”以及此描述:
不好的做法 - 调用的方法只能在doPrivileged块中调用 插件:findbugs密钥:DP_DO_INSIDE_DO_PRIVILEGED 此代码调用需要安全权限检查的方法。如果此代码将被授予安全权限,但可能由没有安全权限的代码调用,则调用需要在doPrivileged块中进行。
我的问题为什么这么糟糕?我该如何解决呢?
答案 0 :(得分:8)
来自field#setAccessible(boolean)
的Javadoc:
首先,如果有安全管理器,则使用ReflectPermission(&#34; suppressAccessChecks&#34;)权限调用其checkPermission方法。
如果没有安装SecurityManager
,程序将运行正常。但是,假设您的代码是作为共享库编写的,并且它恰好被某个已设置安全管理器的模块使用。在这种情况下,即使代码中的此操作和其他操作被视为可信代码,也可能会拒绝field.setAccessible(true)
权限。这就是FindBugs提出这个警告的原因。
为了保证field.setAccessible(true)
始终被授予权限而不管调用者代码的权限如何,您可以将语句包含在AccessController.doPrivileged
内(您必须使field
AccessController.doPrivileged(new PrivilegedAction() {
@Override
public Object run() {
field.setAccessible(true);
return null;
}
});
1}} final):
{{1}}
答案 1 :(得分:1)
添加上面接受的答案,使用Java 1.7+ lambda表达式,可以通过以下方式实现:
AccessController.doPrivileged((PrivilegedAction) () -> {
field.setAccessible(true);
return null;
});