标签: invokedynamic

使用java.lang.invoke.MethodHandle调用私有方法

如何使用方法句柄调用私有方法?

据我所知,只有两种可公开访问的Lookup实例:

  • MethodHandles.lookup()
  • MethodHandles.publicLookup()

并且都不允许不受限制的私人访问.

有非公众Lookup.IMPL_LOOKUP做我想做的事.是否有一些公共方法来获取它(假设SecurityManager允许它)?

java reflection invokedynamic java-7 methodhandle

8
推荐指数
1
解决办法
2730
查看次数

MethodHandles还是LambdaMetafactory?

在我的工作中,我们有一个用于指定数学公式的DSL,我们后来应用于很多点(数百万).

截至今天,我们构建公式的AST,并访问每个节点以产生我们称之为"评估者"的东西.然后,我们向该求值程序传递公式的参数,并为每个点进行计算.

例如,我们有这个公式: x * (3 + y)

           ??????
     ???????mult???????
     ?     ??????     ?
     ?                ?
  ???v???          ???v???
  ?  x  ?      ????? add ????
  ???????      ?   ???????  ?
               ?            ?
            ???v???      ???v???
            ?  3  ?      ?  y  ?
            ???????      ???????
Run Code Online (Sandbox Code Playgroud)

我们的评估员将为每个步骤发出"评估"对象.

这种方法易于编程,但效率不高.

所以我开始研究方法句柄来构建一个"组合"的方法句柄,以加快最近的速度.

这样的事情:我有我的"算术"课:

public class Arithmetics {

  public static double add(double a, double b){
      return a+b;
  }

  public static double mult(double a, double b){
      return a*b;
  }

}
Run Code Online (Sandbox Code Playgroud)

在构建我的AST时,我使用MethodHandles.lookup()来直接获取它们的句柄并组合它们.沿着这些方向的东西,但在一棵树上:

Method add = ArithmeticOperator.class.getDeclaredMethod("add", double.class, double.class);
Method mult = ArithmeticOperator.class.getDeclaredMethod("mult", double.class, …
Run Code Online (Sandbox Code Playgroud)

java lambda invokedynamic java-8 methodhandle

8
推荐指数
1
解决办法
728
查看次数

如何使用Object []数组调用MethodHandle.invokeExact()?

Java的MethodHandle.invokeExact(Object ... args)采用可变长度的参数列表.但是,当我尝试传递Object []而不是列表数组时,我收到错误.见下文:

private void doIt() throws Throwable {

    Method meth = Foo.class.getDeclaredMethods()[0];

    MethodHandles.Lookup lookup = MethodHandles.lookup();
    MethodHandle mh = lookup.unreflect(meth);

    Foo foo = new Foo();
    String myStr = "aaa";
    Integer myInt = new Integer(10);
    Object [] myArray = {foo, myStr, myInt};

    mh.invokeExact(foo, myStr, myInt); // prints "Called aaa 10"
    mh.invokeExact(myArray); // throws Exception
}

class Foo {
    public void bar(String myStr, Integer myInt) {
        System.out.println("Called " + myStr + " " + myInt);
    }
}
Run Code Online (Sandbox Code Playgroud)

第二次调用invokeExact()会产生以下异常:

Exception in …
Run Code Online (Sandbox Code Playgroud)

java eclipse reflection invokedynamic methodhandle

7
推荐指数
1
解决办法
1407
查看次数

为什么Java8和Scala2.12 lambda缓存有区别?

Java代码

package lambda_cache_example_java;

interface Semigroup1<A> {
  public A append(A a1, A a2);
}

interface Semigroup2<A> {
  public A append(A a1, A a2);

  public interface Foo{}
  public class Bar{}
}

class Main {
  static Semigroup1<Integer> intSemigroup1() {
    return (a1, a2) -> a1 + a2;
  }

  static Semigroup2<Integer> intSemigroup2() {
    return (a1, a2) -> a1 + a2;
  }

  public static void main(String[] args) {
    Semigroup1<Integer> x1 = intSemigroup1();
    Semigroup1<Integer> x2 = intSemigroup1();
    System.out.println(x1);
    System.out.println(x2);
    System.out.println(x1 == x2); // same instance

    Semigroup2<Integer> y1 …
Run Code Online (Sandbox Code Playgroud)

lambda jvm scala invokedynamic java-8

7
推荐指数
1
解决办法
396
查看次数

使用ASM生成工作invokedynamic指令

我正在通过ASM使用Java字节码,并试图让一个简单的invokedynamic示例正常运行.我觉得好像我从根本上误解了invokedynamic应该如何工作.这是我到目前为止所尝试的:

Test2.java我有一个静态方法,我希望调用和我的引导方法:

public static int plus(int a, int b) {  // method I want to dynamically invoke
    return a + b;
}

public static CallSite bootstrap(MethodHandles.Lookup caller, String name,
        MethodType type) throws Exception {

    MethodHandle mh = MethodHandles.lookup().findStatic(Test2.class,
            "plus", MethodType.methodType(int.class, int.class, int.class));

    return new ConstantCallSite(mh);
}
Run Code Online (Sandbox Code Playgroud)

现在,在Test.java我生成一个使用ASM Example.class在包中调用的类文件package1:

mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main",
        "([Ljava/lang/String;)V", null, null);
mv.visitCode();

mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
        "Ljava/io/PrintStream;");

mv.visitIntInsn(BIPUSH, 42);
mv.visitIntInsn(BIPUSH, 24);

// mv.visitMethodInsn(INVOKESTATIC, "package1/Test2", …
Run Code Online (Sandbox Code Playgroud)

java bytecode .class-file invokedynamic

6
推荐指数
1
解决办法
2108
查看次数

使用Grails和Groovy调用动态功能

在Groovy 2.1中,增加了全面支持invokedynamic(参见此处此处).

为了使用这个功能,它看起来像JDK7和"indy"Groovy jar.

我正在使用Grails 2.4.3,使用JDK7和Groovy 2.3,所以看起来这应该是可能的,而且看起来它似乎有点帮助Grails性能.

我的问题是:Grails可以利用这个,如果是这样的话怎么样?

是一个类似的问题,从一段时间以来,涵盖了类似的基础.

grails groovy invokedynamic

6
推荐指数
0
解决办法
432
查看次数

使用--indy执行冒泡排序的速度要慢5倍

我写了一个冒泡排序的实现,与Groovy一起玩,看看是否--indy对性能有任何明显的影响.

从本质上讲,它对一千个随机整数的列表进行了一千次排序,并测量了对列表进行排序的平均执行时间.

列表Integer[]的一半是一个,另一半是一个ArrayList<Integer>.

结果让我很困惑:

$ groovyc BubbleSort.groovy
$ time java -cp ~/.gvm/groovy/current/embeddable/groovy-all-2.4.3.jar:. BubbleSort
Average: 22.926ms
Min: 11.202ms
[...] 26.48s user 0.84s system 109% cpu 25.033 total

$ groovyc --indy BubbleSort.groovy
$ time java -cp ~/.gvm/groovy/current/embeddable/groovy-all-2.4.3-indy.jar:. BubbleSort
Average: 119.766ms
Min: 68.251ms
[...] 166.05s user 1.52s system 135% cpu 2:03.82 total
Run Code Online (Sandbox Code Playgroud)

查看基准测试运行时的CPU使用情况,编译时的CPU使用率--indy要比非编译时高很多.

CPU使用率

这引起了我的兴趣所以我再次运行基准测试 - 但这次启用了Yourkit代理和CPU跟踪.以下是录制的呼叫树:

没有--indy: 不使用<code>--indy</code>:
<a rel=使用<code>--indy</code>代码速度慢得多.</p>

<p>没有<code>--indy</code>(1s比例):
<a rel=没有<code>--indy</code>(60s规模):
<a rel=<code>--indy</code>但在编译时则在12.5%和~35%之间变化很大<code>--indy</code>.更令人困惑的是,Yourkit只报告一个活动线程(我的代码只使用主线程),但仍然设法保留两个半核心.</p>

<p>编译的代码<code>--indy</code>在开始时也使用了大量的内核时间,虽然这会在一段时间内下降并稳定在0% …</p> </div>
        <p>
          <a href=groovy jruby invokedynamic java-8

6
推荐指数
1
解决办法
653
查看次数

如何使用`MethodHandle`模仿`tableswitch`?

上下文:我一直在对使用invokedynamic和手动生成字节码之间的差异进行基准测试(这是在决定面向 JVM 的编译器是应该发出更冗长的“传统”字节码还是只是invokedynamic使用巧妙的引导方法调用)的上下文中。在这样做时,将字节码映射到MethodHandles至少同样快的组合器是非常简单的,除了tableswitch.

问题:是否有模仿tableswitch使用的技巧MethodHandle?我试着用一个跳转表来模仿它:使用一个常量MethodHandle[],用 索引到它arrayElementGetter,然后用 调用找到的句柄MethodHandles.invoker。然而,当我通过 JMH 运行它时,它最终比原始字节码慢了大约 50%。

下面是生成方法句柄的代码:

private static MethodHandle makeProductElement(Class<?> receiverClass, List<MethodHandle> getters) {
    MethodHandle[] boxedGetters = getters
        .stream()
        .map(getter -> getter.asType(getter.type().changeReturnType(java.lang.Object.class)))
        .toArray(MethodHandle[]::new);

    MethodHandle getGetter = MethodHandles      // (I)H
        .arrayElementGetter(MethodHandle[].class)
        .bindTo(boxedGetters);
    MethodHandle invokeGetter = MethodHandles.permuteArguments( // (RH)O
        MethodHandles.invoker(MethodType.methodType(java.lang.Object.class, receiverClass)),
        MethodType.methodType(java.lang.Object.class, receiverClass, MethodHandle.class),
        1,
        0
    );

    return MethodHandles.filterArguments(invokeGetter, 1, getGetter);
}
Run Code Online (Sandbox Code Playgroud)

这是初始字节码(我试图用一个invokedynamic调用替换它)

  public java.lang.Object productElement(int); …
Run Code Online (Sandbox Code Playgroud)

jvm bytecode invokedynamic methodhandle

6
推荐指数
1
解决办法
137
查看次数

指定 1.8 以外的 -jvm-target / jvmTarget 版本的好处

从 Kotlin 1.6.0 开始,对于 Kotlin/JVM 项目,可以指定-jvm-target version最高可达 Java 的选项17,请参阅常规Gradle 插件文档。

这样做有什么好处呢?除了 的默认值之外,我找不到太多关于指定其他值的好处1.8

我能找到的唯一的东西是:

两者对我来说似乎都可以忽略不计。

特别是因为当指定更高的目标时,人们将失去在使用 Java 1.8 的项目中使用生成的工件的能力,这似乎是不可取的,尤其是对于库而言。

我在这里错过了什么吗?

java jvm invokedynamic kotlin kotlin-java-interop

6
推荐指数
1
解决办法
2051
查看次数

Lambda匹配FunctionalInterface的签名,但"没有".你怎么解释这个论点完全被传递了?

我目前正在研究这个项目.它运作得非常好.

然而,在重新阅读README之后,我开始怀疑如何记录一些困扰我的东西......

引用这个例子,并忘记抛出异常,它的内容如下:

Files.list(somePath).map(Path::toRealPath).forEach(System.out::println)
Run Code Online (Sandbox Code Playgroud)

好.现在,Path涉及的方法就是这个.当然,我们没有通过任何LinkOption.

再说一遍:让我们忘记它抛出任何异常.

流的.map()需要Function作为参数.此接口用于Function<T, R>定义为:

R apply(T t);
Run Code Online (Sandbox Code Playgroud)

但我使用的方法不接受任何参数.乍一看,它似乎不匹配Function,对吗?除了那个...

它可以写成:

path -> path.toRealPath()
Run Code Online (Sandbox Code Playgroud)

因此,如果方法引用没有参数,或类似的东西,它看起来像使用的机制有点能够调用"流对象"上的方法...

我想相应地记录下来,我在这里遗漏了一些东西.

我错过了什么?

java lambda invokedynamic java-8

5
推荐指数
1
解决办法
95
查看次数