Home | History | Annotate | Download | only in native
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "java_lang_reflect_Parameter.h"
     18 
     19 #include "android-base/stringprintf.h"
     20 #include "nativehelper/jni_macros.h"
     21 
     22 #include "art_method-inl.h"
     23 #include "base/utils.h"
     24 #include "common_throws.h"
     25 #include "dex/dex_file-inl.h"
     26 #include "dex/dex_file_annotations.h"
     27 #include "jni_internal.h"
     28 #include "native_util.h"
     29 #include "scoped_fast_native_object_access-inl.h"
     30 
     31 namespace art {
     32 
     33 using android::base::StringPrintf;
     34 
     35 static jobject Parameter_getAnnotationNative(JNIEnv* env,
     36                                              jclass,
     37                                              jobject javaMethod,
     38                                              jint parameterIndex,
     39                                              jclass annotationType) {
     40   ScopedFastNativeObjectAccess soa(env);
     41   if (UNLIKELY(javaMethod == nullptr)) {
     42     ThrowNullPointerException("javaMethod == null");
     43     return nullptr;
     44   }
     45 
     46   ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
     47   if (method->IsProxyMethod()) {
     48     return nullptr;
     49   }
     50 
     51   uint32_t parameter_count = method->GetParameterTypeList()->Size();
     52   if (UNLIKELY(parameterIndex < 0 || static_cast<uint32_t>(parameterIndex) >= parameter_count)) {
     53     ThrowIllegalArgumentException(
     54         StringPrintf("Illegal parameterIndex %d for %s, parameter_count is %d",
     55                      parameterIndex,
     56                      method->PrettyMethod().c_str(),
     57                      parameter_count).c_str());
     58     return nullptr;
     59   }
     60 
     61   uint32_t annotated_parameter_count = annotations::GetNumberOfAnnotatedMethodParameters(method);
     62   if (annotated_parameter_count == 0u) {
     63     return nullptr;
     64   }
     65 
     66   // For constructors with implicit arguments, we may need to adjust
     67   // annotation positions based on whether the implicit parameters are
     68   // expected to known and not just a compiler implementation detail.
     69   if (method->IsConstructor()) {
     70     StackHandleScope<1> hs(soa.Self());
     71     // If declaring class is a local or an enum, do not pad parameter
     72     // annotations, as the implicit constructor parameters are an
     73     // implementation detail rather than required by JLS.
     74     Handle<mirror::Class> declaring_class = hs.NewHandle(method->GetDeclaringClass());
     75     if (annotations::GetEnclosingMethod(declaring_class) == nullptr && !declaring_class->IsEnum()) {
     76       // Adjust the parameter index if the number of annotations does
     77       // not match the number of parameters.
     78       if (annotated_parameter_count <= parameter_count) {
     79         // Workaround for dexer not inserting annotation state for implicit parameters (b/68033708).
     80         uint32_t skip_count = parameter_count - annotated_parameter_count;
     81         DCHECK_GE(2u, skip_count);
     82         if (parameterIndex < static_cast<jint>(skip_count)) {
     83           return nullptr;
     84         }
     85         parameterIndex -= skip_count;
     86       } else {
     87         // Workaround for Jack erroneously inserting implicit parameter for local classes
     88         // (b/68033708).
     89         DCHECK_EQ(1u, annotated_parameter_count - parameter_count);
     90         parameterIndex += static_cast<jint>(annotated_parameter_count - parameter_count);
     91       }
     92     }
     93   }
     94 
     95   StackHandleScope<1> hs(soa.Self());
     96   Handle<mirror::Class> klass(hs.NewHandle(soa.Decode<mirror::Class>(annotationType)));
     97   return soa.AddLocalReference<jobject>(
     98       annotations::GetAnnotationForMethodParameter(method, parameterIndex, klass));
     99 }
    100 
    101 static JNINativeMethod gMethods[] = {
    102   FAST_NATIVE_METHOD(
    103       Parameter,
    104       getAnnotationNative,
    105       "(Ljava/lang/reflect/Executable;ILjava/lang/Class;)Ljava/lang/annotation/Annotation;"),
    106 };
    107 
    108 void register_java_lang_reflect_Parameter(JNIEnv* env) {
    109   REGISTER_NATIVE_METHODS("java/lang/reflect/Parameter");
    110 }
    111 
    112 }  // namespace art
    113