1. 主页 > 大智慧

解决Java反射调用私有方报错:参数与权限问题


馃 涓轰粈涔堝埆浜鸿兘璋冪鏈夋柟娉曪紝鎴戝嵈鎶ラ敊锛?/h3>

"鏄庢槑鐓х潃鏁欑▼鍐欑殑浠g爜锛屾€庝箞涓€杩愯灏辨姤閿欙紵"杩欐槸涓嶆槸浣犲湪瀛ava鍙嶅皠鏃剁殑鐪熷疄鍐欑収锛熶粖澶╁挶浠氨鍞犲敔杩欎釜璁╂柊鎵嬫姄鐙傜殑闂鈥斺€斺€?strong>鈥嬪弽灏勮皟鐢ㄧ鏈夋柟娉曠殑鎶ラ敊鈥?/strong>鈥嬨€?/p>

涓句釜鐪熷疄渚嬪瓙锛氬皬鏄庢兂鐢ㄥ弽灏勮皟鐢ㄥ悓浜嬪啓鐨勫伐鍏风被閲屼竴涓?code>calculateSalary()绉佹湁鏂规硶锛岀粨鏋滆涔堟彁绀?code>NoSuchMethodException锛岃涔堝脊鍑?code>IllegalAccessException銆傝繖灏卞儚鎷跨潃涓囪兘閽ュ寵鍗存墦涓嶅紑淇濋櫓绠憋紝浣犺姘斾笉姘旓紵


馃攽 绗竴閬撳潕锛氭潈闄愰棶棰橈紙IllegalAccessException锛?/h3>

褰撶湅鍒版姤閿欎俊鎭噷鍑虹幇IllegalAccessException鏃讹紝鍏垚鏄Е鍙戜簡Java鐨勨€?strong>鈥嬭闂帶鍒舵満鍒垛€?/strong>鈥嬨€傝繖灏卞ソ姣斿叕鍙搁棬绂佲€斺€旀病宸ョ墝鐨勪汉鎯宠繘鐮斿彂閮紵淇濆畨鐩存帴缁欎綘鎷︿笅鏉ワ紒

鈥?strong>鈥嬬牬瑙eЭ鍔夸笁姝ヨ蛋鈥?/strong>鈥嬶細

  1. 鈥?strong>鈥嬫毚鍔涘紑閿佹硶鈥?/strong>鈥嬶細鐢?code>method.setAccessible(true)
    杩欏氨鏄憲鍚嶇殑"鏉冮檺寮€鍏?锛岀浉褰撲簬缁欎繚瀹夐€掍簡鏍圭儫锛?鍝ワ紝鎴戝氨杩涘幓閫佷釜鏂囦欢"銆?/p>

    java澶嶅埗
    Method method = clazz.getDeclaredMethod("calculateSalary");
    method.setAccessible(true);  //鉁ㄥ叧閿搷浣滐紒
    method.invoke(obj);

    娉ㄦ剰锛欽ava 9寮€濮嬭繖鎷涘彲鑳藉け鏁堬紝寰楀湪鍚姩鏃跺姞--add-opens鍙傛暟銆?/em>

  2. 鈥?strong>鈥嬫洸绾挎晳鍥芥硶鈥?/strong>鈥嬶細閫氳繃鍏叡鏂规硶闂存帴璋冪敤
    姣斿鍦ㄧ洰鏍囩被閲屽姞涓?code>public void callPrivateMethod(){ calculateSalary(); }銆傚氨鍍忔壘鍐呴儴鍛樺伐甯繖鍒峰崱锛岃櫧鐒堕夯鐑︿絾鏇村畨鍏ㄣ€?/p>

  3. 鈥?strong>鈥嬬粓鏋佸妗堚€?/strong>鈥嬶細鑷畾涔塖ecurityManager
    杩欎釜閫傚悎妗嗘灦寮€鍙戣€咃紝鏅€氶」鐩厧鐢ㄣ€傚氨鍍忚嚜宸卞綋淇濆畨闃熼暱锛岄噸鏂板埗瀹氶棬绂佽鍒欍€?/p>

鈥?strong>鈥嬫暟鎹璇濃€?/strong>鈥嬶細鏌愪唬鐮佸钩鍙扮粺璁℃樉绀猴紝绾?8%鐨勫弽灏勬姤閿欓兘鏄潈闄愰棶棰樺鑷寸殑銆?/p>


馃З 绗簩閬撳潕锛氬弬鏁板涓嶄笂锛圢oSuchMethodException锛?/h3>

浣犱互涓烘柟娉曞悕鍐欏灏辫浜嗭紵Too young锛佸弬鏁扮被鍨嬫墠鏄殣钘廈OSS銆傝繖灏卞儚缃戣喘濉湴鍧€鈥斺€斿啓閿欎竴涓暟瀛楋紝蹇€掑氨閫佷笉鍒颁綘瀹躲€?/p>

鈥?strong>鈥嬮伩鍧戞寚鍗椻€?/strong>鈥嬶細

  1. 鈥?strong>鈥嬬簿纭尮閰嶆硶鈥?/strong>鈥?br/> 鍋囪瑕佽皟鐨勬柟娉曠鍚嶆槸void save(String id, int version)锛岃繖涔堝啓鍑嗘病閿欙細

    java澶嶅埗
    // 鉁呮纭ず鑼?/span>
    Method method = clazz.getDeclaredMethod("save", String.class, int.class);

    浣嗚鏄啓鎴愯繖鏍?..

    java澶嶅埗
    // 鉂屾浜″啓娉?/span>
    Method method = clazz.getDeclaredMethod("save", Object.class, Integer.class);

    绛夌潃浣犵殑灏辨槸绾㈠饯褰ょ殑NoSuchMethodException銆?/p>

  2. 鈥?strong>鈥嬫硾鍨嬪鐞嗗鎷涒€?/strong>鈥?br/> 閬囧埌娉涘瀷鏂规硶鍒厡锛岃浣廕ava浼氭摝闄ょ被鍨嬩俊鎭€傛瘮濡?code> void process(T data)锛屽弽灏勬椂瑕佸綋鎴?code>Object澶勭悊锛?/p>

    java澶嶅埗
    Method method = clazz.getDeclaredMethod("process", Object.class);

鈥?strong>鈥嬪疄鎴樻渚嬧€?/strong>鈥嬶細鏌愮數鍟嗙郴缁熸浘鍥犳妸LocalDateTime.class鍐欐垚Date.class锛屽鑷翠績閿€娲诲姩閰嶇疆澶辫触锛岀洿鎺ユ崯澶?0涓囪鍗曘€?/p>


馃洜 缁勫悎鎷冲疄鎴橈細瀹屾暣瑙e喅娴佺▼

鍜变滑鐢ㄥ鍗栫郴缁熺殑浼樻儬璁$畻鍦烘櫙锛屾墜鎶婃墜婕旂ず姝g‘鎿嶄綔锛?/p>

  1. 鈥?strong>鈥嬭幏鍙栫被淇℃伅鈥?/strong>鈥?/p>

    java澶嶅埗
    Class<?> clazz = Class.forName("com.feast.CouponService");
  2. 鈥?strong>鈥嬬簿鍑嗗畾浣嶆柟娉曗€?/strong>鈥?/p>

    java澶嶅埗
    // 鏂规硶绛惧悕锛歱rivate BigDecimal calculate(User user, List items)
    Method method = clazz.getDeclaredMethod(
        "calculate", 
        User.class, 
        List.class
    );
  3. 鈥?strong>鈥嬬獊鐮存潈闄愬皝閿佲€?/strong>鈥?/p>

    java澶嶅埗
    method.setAccessible(true);
  4. 鈥?strong>鈥嬬ǔ濡ヤ紶鍙傝皟鐢ㄢ€?/strong>鈥?/p>

    java澶嶅埗
    Object result = method.invoke(
        couponService, 
        new User("13800138000"), 
        Arrays.asList(item1, item2)
    );

鈥?strong>鈥嬮伩鍧慣IP鈥?/strong>鈥嬶細閬囧埌閲嶈浇鏂规硶鏃讹紝鍙互鐢?code>clazz.getDeclaredMethods()鎵撳嵃鎵€鏈夋柟娉曠鍚嶅姣斻€?/p>


鈿?鎬ц兘涓庡畨鍏ㄧ殑骞宠 鏈?/h3>

铏界劧鍙嶅皠寰堝己澶э紝浣嗕篃涓嶈兘婊ョ敤銆傛牴鎹祴璇曟暟鎹紝鍙嶅皠璋冪敤姣旂洿鎺ヨ皟鐢ㄦ參50鍊嶄互涓娿€傝繖閲屾湁鍑犱釜浼樺寲寤鸿锛?/p>

  1. 鈥?strong>鈥嬬紦瀛楳ethod瀵硅薄鈥?/strong>鈥?br/> 鎶婇珮棰戜娇鐢ㄧ殑Method瀛樺埌闈欐€丮ap閲岋紝閬垮厤閲嶅鑾峰彇鐨勫紑閿€銆?/p>

  2. 鈥?strong>鈥婱ethodHandle榛戠鎶€鈥?/strong>鈥?br/> JDK7+鍙互鐢ㄨ繖涓洿楂樻晥鐨凙PI锛?/p>

    java澶嶅埗
    MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
    MethodHandle handle = lookup.findVirtual(clazz, "methodName", methodType);
    handle.invoke(obj);
  3. 鈥?strong>鈥嬮槻寰℃€х紪绋嬧€?/strong>鈥?/p>

    • 鐢?code>Modifier.isPrivate(method.getModifiers())鎻愬墠鍒ゆ柇
    • 鍦╢inally鍧楅噸缃闂潈闄?/li>
    • 瀵规晱鎰熸柟娉曟坊鍔?code>@ReflectPermission鑷畾涔夋敞瑙?/li>

馃専 鐙瑙佽В锛氬弽灏勮涓嶈鐢紵

鏈€杩戞湁涓尯鏈夋剰鎬濈殑璋冩煡锛氬湪100涓狫ava寮€婧愰」鐩腑锛?7%鐨勫弽灏勪娇鐢ㄥ満鏅泦涓湪妗嗘灦灞傦紙姣斿Spring鐨処oC锛夛紝鍙湁13%鍑虹幇鍦ㄤ笟鍔′唬鐮侀噷銆傝繖璇存槑浠€涔堬紵鈥?strong>鈥嬪弽灏勬槸鎶婄憺澹啗鍒€锛岄€傚悎涓撲笟閫夋墜鍦ㄧ壒瀹氬満鏅娇鐢ㄢ€?/strong>鈥嬨€?/p>

鎵€浠ョ粰鏂版墜鐨勫缓璁槸锛?/p>

  1. 涓氬姟浠g爜灏介噺鐢ㄦ帴鍙e拰璁捐妯″紡鏇夸唬鍙嶅皠
  2. 纭疄瑕佺敤鏃讹紝璁板緱鍔犺缁嗘敞閲?/li>
  3. 鍗曞厓娴嬭瘯瑕嗙洊鐜囧繀椤昏揪鍒?0%浠ヤ笂

灏卞儚鑰佸徃鏈哄父璇寸殑锛?鍙嶅皠鐜╁緱6锛屽姞鐝皯涓嶄簡锛涚敤瀵瑰満鏅椂锛岀湡棣欒窇涓嶄簡锛?

本文由嘻道妙招独家原创,未经允许,严禁转载