private HeapItem getSafeField(Field field, Object instance, ExecutionContext context, Op op, ExceptionFactory exceptionFactory) { HeapItem item = null; try { Object getObject = field.get(instance); String type = ClassNameUtils.toInternal(field.getType()); item = new HeapItem(getObject, type); } catch (IllegalArgumentException | IllegalAccessException e) { String message = e.getMessage(); VirtualMethod callingMethod = context.getCallerContext().getMethod(); VirtualType callingClass = callingMethod.getDefiningClass(); message = message.replace(java_lang_reflect_Field_get.class.getName(), callingClass.getBinaryName()); Throwable exception = exceptionFactory.build(op, e.getClass(), message); setException(exception); } return item; }
private static void testNegativeCase(String fieldName, String callingMethodSignature) throws Exception { spawnVM(); ExecutionContext context = buildContext(vm); ExecutionContextMethod fieldGet = test(vm, context, fieldName, callingMethodSignature, false); Set<Throwable> exceptions = fieldGet.getExceptions(); assertEquals("Should have one exception", 1, exceptions.size()); VirtualType callingClass = context.getCallerContext().getMethod().getDefiningClass(); VirtualField field = context.getMethod().getDefiningClass().getField(fieldName); String error = callingClass.getBinaryName() + " can't access a member of " + DUMMY_CLASS_NAME_BINARY + " with modifiers \"" + Modifier.toString(field.getField().getAccessFlags()) + "\""; Throwable actualException = exceptions.iterator().next(); assertEquals(IllegalAccessException.class, actualException.getClass()); assertEquals(error, actualException.getMessage()); }
@Override public void execute(VirtualMachine vm, Op op, ExecutionContext context) { MethodState mState = context.getMethodState(); HeapItem fieldItem = mState.peekParameter(0); HeapItem instanceItem = mState.peekParameter(1); Field field = (Field) fieldItem.getValue(); int accessFlags = field.getModifiers(); String fieldClassName = ClassNameUtils.toInternal(field.getDeclaringClass()); if (!field.isAccessible()) { VirtualType callingClass = context.getCallerContext().getMethod().getDefiningClass(); ClassManager classManager = vm.getClassManager(); VirtualClass fieldClass = classManager.getVirtualClass(fieldClassName); boolean hasAccess = checkAccess(callingClass, fieldClass, accessFlags, op, vm.getExceptionFactory()); if (!hasAccess) { return; } } Object instance = instanceItem.getValue(); HeapItem getItem = get(field, instance, fieldClassName, accessFlags, context, vm, op); mState.assignReturnRegister(getItem); }