简单例子

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType; public class MHT { private String name; // 构造方法
public MHT(String name) {
this.name = name;
} // 公共方法
public String publicTest() {
return name + "'publicTest";
} // 静态方法
public static String publicStaticTest() {
return "'publicStaticTest";
} // 私有方法
private String test(int param) {
switch (param) {
case 1:
return "suych1";
case 2:
return "suych2";
case 3:
return "suych3";
default:
return "suych4";
}
} // Get方法
public String getName() {
return name;
} // Set方法
public void setName(String name) {
this.name = name;
} public static void main(String[] args) throws Throwable {
// 构造方法
MethodType mtConstructor = MethodType.methodType(void.class, String.class); //返回值类型,参数类型
MethodHandle mhConstructor = MethodHandles.lookup().findConstructor(MHT.class, mtConstructor);
MHT businessHandle = ( MHT ) mhConstructor.invokeExact("suych");
System.out.println(businessHandle.getName()); // 公共方法
MethodType mtPublic = MethodType.methodType(String.class); //返回值类型
MethodHandle mhPublic = MethodHandles.lookup().findVirtual(MHT.class, "publicTest", mtPublic);
String resultPublic = ( String ) mhPublic.invokeExact(businessHandle);
System.out.println(resultPublic); // 静态方法
MethodType mtPublicStatic = MethodType.methodType(String.class);
MethodHandle mhPublicStatic = MethodHandles.lookup().findStatic(MHT.class, "publicStaticTest",
mtPublicStatic);
String resultPublicStatic = ( String ) mhPublicStatic.invokeExact();
System.out.println(resultPublicStatic); // 私有方法
MethodType mtPrivate = MethodType.methodType(String.class, int.class); //返回值类型,参数类型
MethodHandle mhPrivate = MethodHandles.lookup().findSpecial(MHT.class, "test", mtPrivate,
MHT.class);
String resultPrivate = ( String ) mhPrivate.invokeExact(businessHandle, 1);
System.out.println(resultPrivate); // Set方法
MethodHandle mhSet = MethodHandles.lookup().findSetter(MHT.class, "name", String.class);
mhSet.invokeExact(businessHandle, "A");
System.out.println(businessHandle.name); // Get方法
MethodHandle mhGet = MethodHandles.lookup().findGetter(MHT.class, "name", String.class);
String resultGet = ( String ) mhGet.invokeExact(businessHandle);
System.out.println(resultGet); } }

输出:

suych   构造方法输出
suych'publicTest 公共方法输出
'publicStaticTest 静态方法输出
suych1 私有方法输出
A Set方法输出
A Get方法输出

基于MethodHandle实现的调用Runtime执行系统命令

import java.io.InputStream;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Scanner; /**
* @author yz
*/
public class MethodHandlesTest { public static void main(String[] args) {
try {
String str = "arp -a";
Class runtimeClass = Runtime.class;
MethodHandles.Lookup lookup = MethodHandles.lookup(); // Runtime rt = Runtime.getRuntime()
MethodHandle methodHandle = lookup.findStatic(
runtimeClass, "getRuntime", MethodType.methodType(runtimeClass)
); // 获取Runtime的exec方法
MethodHandle execMethod = lookup.findVirtual(
runtimeClass, "exec", MethodType.methodType(Process.class, new Class[]{
String.class
})
); // 获取Process的getInputStream方法
MethodHandle inputStreamMethod = lookup.findVirtual(
Process.class, "getInputStream", MethodType.methodType(InputStream.class)
); // 调用Runtime.getRuntime().exec(xxx).getInputStream()
InputStream in = (InputStream) inputStreamMethod.invoke(
execMethod.invoke(methodHandle.invoke(), str)
); // 输出InputStream内容到
Scanner scanner = new Scanner(in).useDelimiter("\\A");
System.out.println(scanner.hasNext() ? scanner.next() : "");
} catch (Throwable t) {
t.printStackTrace();
}
} }

JAVA反射修改private,final值

FinalName.java

class FinalName {
public final String name="init";
}

PrivateName.java

class PrivateName {
private String name = "init";
public String getName() {
return name;
}
}

Test.java

import java.lang.reflect.Field;

public class Test {
public static void main(String[] args) throws Exception {
PrivateName privateName = new PrivateName();
FinalName finalName = new FinalName();
// System.out.println(finalName.name);
modify(privateName, "name", "private change");
modify(finalName, "name", "final change");
System.out.println(privateName.getName());
System.out.println(finalName.name);
}
public static void modify(Object object, String fieldName, Object newFieldValue) throws Exception {
Field field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, newFieldValue);
System.out.println(field.get(object));
}
}

输出结果,private修饰的变量结果已经被修改,但是final修改正常但是获取的依然是原先的值,这是因为内联优化。

private change
final change
private change
init

如果将FinalName.java修改为通过构造方法给final修饰的属性赋值。

class FinalName {
public final String name; FinalName(String name) {
this.name = name;
}
}
FinalName Finalname = FinalName("aaaaaa");

再次运行Test.java,发现final修饰的变量已经被修改。

private change
final change
private change
final change

总结:private修饰的变量可以通过反射的方法将值修改,需要设置访问权限为true。field.setAccessible(true);

final修饰的变量如果是直接赋值,则对属性值进行修改无效。如果是通过构造方法修改属性的值,则可以通过反射的方法修改final修饰的变量。

通过反射方式执行命令。

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Scanner;
public class ReflectionTest { public static void exec() {
try {
System.out.println(Runtime.class.getMethod("exec", String.class).invoke(Runtime.class.getMethod("getRuntime").invoke(null), "curl -i localhost:8000"));
} catch (Exception e) {
e.printStackTrace();
}
} public static void main(String[] args) {
try {
String str = "arp -a"; // java.lang.Runtime
String runtime = new String(new byte[]{106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 82, 117, 110, 116, 105, 109, 101}); // Runtime.class
Class<?> c = Class.forName(runtime); // 获取getRuntime方法,Runtime.getRuntime()
Method m1 = c.getMethod(new String(new byte[]{103, 101, 116, 82, 117, 110, 116, 105, 109, 101})); // 获取Runtime的exec方法,rt.exec(xxx)
Method m2 = c.getMethod(new String(new byte[]{101, 120, 101, 99}), String.class); // Runtime.getRuntime().exec(str)
Object obj2 = m2.invoke(m1.invoke(null), str); // 获取命令执行结果Process类的getInputStream()方法
Method m = obj2.getClass().getMethod(new String(new byte[]{103, 101, 116, 73, 110, 112, 117, 116, 83, 116, 114, 101, 97, 109}));
m.setAccessible(true); // process.getInputStream()
InputStream in = (InputStream) m.invoke(obj2, new Object[]{}); // 输出InputStream内容到
Scanner scanner = new Scanner(in).useDelimiter("\\A");
System.out.println(scanner.hasNext() ? scanner.next() : "");
} catch (Throwable t) {
t.printStackTrace();
}
} }

看下为什么获取命令执行结果Process类的getInputStream()方法访问权限需要设置true。

跟入java.lang.ProcessImpl类



getInputStream方法返回stdout_stream是私有变量





注释掉,则会报下面这样的错误

参考链接:

https://docs.oracle.com/javase/7/docs/api/java/lang/invoke/MethodType.html

https://mp.weixin.qq.com/s/mlqjOlhefcsO9z51cw4S7w

https://blog.csdn.net/yhd723948277/article/details/82661870

# JDK7+ MethodHandle的更多相关文章

  1. 【JVM】2、关于jdk7的MethodHandle类

    关于MethodHandle类,这个类是在jdk1.7之后加入的,这个类的作用类似函数指针的意思 这个类中有一个方法 这里我的jdk有一个问题,就是我在进行MethodHandle操作的时候,我们会发 ...

  2. java7 java MethodHandle解析

    简介 JDK6之前我们会使用java反射来实现动态方法调用,多数框架用反射的比较多,例如mybatis.spring等.在JDK7中,新增了java.lang.invoke.MethodHandle( ...

  3. MethodHandle

    JDK7为间接调用方法引入新的API,在java.lang.invoke包下,可以看作为反射的升级版,但它不像反射API那样显得冗长.繁重 主要的类 MethodHandle 方法句柄.对可直接执行的 ...

  4. 阿里云CentOS7系列一 -- 安装JDK7的方法.

    最近因为数据采集以及生产环境冲突.导入windows Server 2008系统经常死机.经讨论决定把采集服务程序和生产服务进行分开.采集程序通过windows Server2008运行.而生产程序通 ...

  5. JDK7和JDK8一些重要新特性

    jdk7新特性(部分) switch支持字符串 List AutoCloseable接口实现自动关闭,在try()中 新增获取环境信息的工具方法,getJavaHomeDir,getUserHomeD ...

  6. 《java JDK7 学习笔记》之异常处理

    1.java中所有的错误都会被打包为对象,JVM会尝试执行try区块中的程序代码,如果发生错误,执行流程会跳离错误发生点,然后比较catch括号中声明的异常类型,是否符合被抛出的错误对象类型,如果是的 ...

  7. MyEclipse10的一些问题(git插件,jdk7)

    egit: MyEclipse10 要装 egit2.3,版本错了安装不成功; jdk7: 10.5好像是不支持JDK1.7的,换成10.7; JDK1.7中的switch支持String类型的,1. ...

  8. win7 安装JDK7和JDK8后,卸载JDK8后出错

    这是本人学习Java过程中遇到的一些问题和解决方法,在此记录,方便本人查看,解决他人疑惑. 本人win7 x64旗舰版,同时安装了JDK7和JDK8,卸载了JDK8之后,cmd命令行输入:java - ...

  9. java 28 - 6 JDK7的新特性

    JDK7的新特性: 二进制字面量 数字字面量可以出现下划线 switch 语句可以用字符串 泛型简化 异常的多个catch合并 try-with-resources 语句 二进制字面量 JDK7开始, ...

随机推荐

  1. JavaScript this指向问题

    this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定,this最终指向调用它的对象. 1.函数调用模式: 当一个函数并非一个对象的属性时,那么它就是被当做函数来调用的.在此种模式下, ...

  2. ubuntu18.04开机提示welcome to emergency mode! after logging in type...的解决办法

    开机就是报错,进不了系统. 原因是我的ubuntu电脑绑定了之前的移动硬盘,而我开机的时候并没有插着移动硬盘. 所以解决办法是,在此命令行下,以root用户的身份(我这里默认是root用户),vim ...

  3. 第十二章 与Spring集成——《跟我学Shiro》

    转发:https://www.iteye.com/blog/jinnianshilongnian-2029717 目录贴:跟我学Shiro目录贴 Shiro的组件都是JavaBean/POJO式的组件 ...

  4. Python的发展历史及其前景

    Python的发展历史 1989年,吉姆·范罗苏姆为打发时间,决定为当时正构思的一个新的脚本语言编写一个解释器.作为派森的狂热粉丝,他以Python命名该项目,使用C进行开发. 1991年发布Pyth ...

  5. 粒子系统与雨的效果 (DirectX11 with Windows SDK)

    前言 最近在学粒子系统,看这之前的<<3D图形编程基础 基于DirectX 11 >>是基于Direct SDK的,而DXSDK微软已经很久没有更新过了并且我学的DX11是用W ...

  6. dropout含义与原理

    含义 在训练过程中,对神经网络单元按照一定比例暂时将其丢弃. 原理 由于网络参数过多,训练数据少,或者训练次数过多,会产生过拟合的现象.dropout产生的一个重大原因就是为了避免过拟合. 每一层的神 ...

  7. 教你成为全栈工程师(Full Stack Developer) 四十五-一文读懂hadoop、hbase、hive、spark分布式系统架构

    转载自http://www.shareditor.com/blogshow?blogId=96 机器学习.数据挖掘等各种大数据处理都离不开各种开源分布式系统,hadoop用于分布式存储和map-red ...

  8. windows服务器入门 初始化数据盘

    本人在寒假的时候自行搭建了一个服务器,在此分享一下我的方法.本人服务器的系统为Windows 2012R2 在后面的讲解中中文英文都会有    所以不用在意系统的语言问题 1)第一步  自然就是打开服 ...

  9. [CF293B]Distinct Paths_搜索_剪枝

    Distinct Paths 题目链接:http://codeforces.com/problemset/problem/293/B 数据范围:略. 题解: 带搜索的剪枝.... 想不到吧..... ...

  10. ElasticSearch总结

    转载自:https://www.cnblogs.com/WessonStar/p/8296781.html 不过我的es版本是7.2.0,然后这里要注意ik分词器放入plugins里是需要有个ik插件 ...