Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default methods #30

Merged
merged 5 commits into from
Sep 5, 2014
Merged

Default methods #30

merged 5 commits into from
Sep 5, 2014

Conversation

Arneball
Copy link
Contributor

No description provided.

@luontola
Copy link
Owner

This fails when merged with master. The version in master processes Retrolambda with itself, so that the Maven plugin (which is Java 6 compatible) can use Retrolambda directly.

[INFO] --- maven-antrun-plugin:1.7:run (retrolambda-inception) @ retrolambda ---
[INFO] Executing tasks

main:
     [exec] Retrolambda DEVELOPMENT-VERSION
     [exec] Bytecode version: 50 (Java 6)
     [exec] Input directory:  C:\DEVEL\Retrolambda\retrolambda\retrolambda\target\classes
     [exec] Output directory: C:\DEVEL\Retrolambda\retrolambda\retrolambda\target\classes
     [exec] Classpath:        C:\DEVEL\Retrolambda\retrolambda\retrolambda\target\classes;C:\Users\ORFJackal\.m2\repository\org\ow2\asm\asm-debug-all\5.0.2\asm-debug-all-5.0.2.jar
     [exec] Visiting interface net/orfjackal/retrolambda/BytecodeTransformingFileVisitor
     [exec] Class is net/orfjackal/retrolambda/BytecodeTransformingFileVisitor, non abstract true, Interfaces are [], default methods are []
     [exec] Visiting interface net/orfjackal/retrolambda/Config
     [exec] Class is net/orfjackal/retrolambda/Config, non abstract true, Interfaces are [], default methods are []
     [exec] Saving lambda class: net/orfjackal/retrolambda/Config$$Lambda$1
     [exec] Interface: java/util/function/Predicate, methods: [public abstract boolean java.util.function.Predicate.test(java.lang.Object), public default java.util.function.Predicate java.util.function.Predicate.and(java.util.function.Predicate), public default java.util.function.Predicate java.util.function.Predicate.or(java.util.function.Predicate), public static java.util.function.Predicate java.util.function.Predicate.isEqual(java.lang.Object), public default java.util.function.Predicate java.util.function.Predicate.negate()]
     [exec] NEED TO CREATE PROXY TO java/util/function/Predicatenull
     [exec] interface java.util.function.Predicate
     [exec] NEED TO CREATE PROXY TO java/util/function/Predicatenull
     [exec] interface java.util.function.Predicate
     [exec] NEED TO CREATE PROXY TO java/util/function/Predicatenull
     [exec] interface java.util.function.Predicate
     [exec] NEED TO CREATE PROXY TO java/util/function/Predicatenull
     [exec] interface java.util.function.Predicate
     [exec] Class is net/orfjackal/retrolambda/Config$$Lambda$1, non abstract true, Interfaces are [java/util/function/Predicate], default methods are [MethodContainer{methodName='or', methodDesc='(Ljava/util/function/Predicate;)Ljava/util/function/Predicate;', interfce='java/util/function/Predicate', signature='null', exceptions=[]}, MethodContainer{methodName='isEqual', methodDesc='(Ljava/lang/Object;)Ljava/util/function/Predicate;', interfce='java/util/function/Predicate', signature='null', exceptions=[]}, MethodContainer{methodName='negate', methodDesc='()Ljava/util/function/Predicate;', interfce='java/util/function/Predicate', signature='null', exceptions=[]}, MethodContainer{methodName='and', methodDesc='(Ljava/util/function/Predicate;)Ljava/util/function/Predicate;', interfce='java/util/function/Predicate', signature='null', exceptions=[]}]
     [exec] VISITEND, CREATING PROXY MethodContainer{methodName='or', methodDesc='(Ljava/util/function/Predicate;)Ljava/util/function/Predicate;', interfce='java/util/function/Predicate', signature='null', exceptions=[]}
     [exec] Find right interfaces for MethodContainer{methodName='or', methodDesc='(Ljava/util/function/Predicate;)Ljava/util/function/Predicate;', interfce='java/util/function/Predicate', signature='null', exceptions=[]} [java/util/function/Predicate]
     [exec] It thinks that the right interface is java/util/function/Predicate
     [exec] VISITEND, CREATING PROXY MethodContainer{methodName='isEqual', methodDesc='(Ljava/lang/Object;)Ljava/util/function/Predicate;', interfce='java/util/function/Predicate', signature='null', exceptions=[]}
     [exec] Find right interfaces for MethodContainer{methodName='isEqual', methodDesc='(Ljava/lang/Object;)Ljava/util/function/Predicate;', interfce='java/util/function/Predicate', signature='null', exceptions=[]} [java/util/function/Predicate]
     [exec] ERROR: Failed to backport lambda class: net/orfjackal/retrolambda/Config$$Lambda$1
     [exec] java.lang.NullPointerException
     [exec]     at net.orfjackal.retrolambda.defaultmethods.ClassModifier$$Lambda$11/1721931908.get(Unknown Source)
     [exec]     at java.util.Optional.orElseThrow(Optional.java:290)
     [exec]     at net.orfjackal.retrolambda.defaultmethods.ClassModifier.findRightInterace(ClassModifier.java:128)
     [exec]     at net.orfjackal.retrolambda.defaultmethods.ClassModifier.visitEnd(ClassModifier.java:95)
     [exec]     at org.objectweb.asm.ClassVisitor.visitEnd(ClassVisitor.java:317)
     [exec]     at net.orfjackal.retrolambda.LambdaClassBackporter$LambdaClassVisitor.visitEnd(LambdaClassBackporter.java:73)
     [exec]     at org.objectweb.asm.ClassReader.accept(ClassReader.java:697)
     [exec]     at org.objectweb.asm.ClassReader.accept(ClassReader.java:506)
     [exec]     at net.orfjackal.retrolambda.LambdaClassBackporter.transform(LambdaClassBackporter.java:22)
     [exec]     at net.orfjackal.retrolambda.LambdaClassSaver.reifyLambdaClass(LambdaClassSaver.java:28)
     [exec]     at net.orfjackal.retrolambda.LambdaClassSaver.saveIfLambda(LambdaClassSaver.java:21)
     [exec]     at net.orfjackal.retrolambda.LambdaClassDumper$ClassChannel.close(LambdaClassDumper.java:144)
     [exec]     at java.nio.channels.Channels$1.close(Channels.java:178)
     [exec]     at java.nio.file.Files.write(Files.java:3300)
     [exec]     at java.lang.invoke.ProxyClassesDumper.dumpClass(ProxyClassesDumper.java:140)
     [exec]     at java.lang.invoke.InnerClassLambdaMetafactory$2.run(InnerClassLambdaMetafactory.java:315)
     [exec]     at java.lang.invoke.InnerClassLambdaMetafactory$2.run(InnerClassLambdaMetafactory.java:312)
     [exec]     at java.security.AccessController.doPrivileged(Native Method)
     [exec]     at java.security.AccessController.doPrivileged(AccessController.java:428)
     [exec]     at java.lang.invoke.InnerClassLambdaMetafactory.spinInnerClass(InnerClassLambdaMetafactory.java:312)
     [exec]     at java.lang.invoke.InnerClassLambdaMetafactory.buildCallSite(InnerClassLambdaMetafactory.java:194)
     [exec]     at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:304)
     [exec]     at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:636)
     [exec]     at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:658)
     [exec]     at net.orfjackal.retrolambda.LambdaReifier.callBootstrapMethod(LambdaReifier.java:110)
     [exec]     at net.orfjackal.retrolambda.LambdaReifier.reifyLambdaClass(LambdaReifier.java:37)
     [exec]     at net.orfjackal.retrolambda.LambdaUsageBackporter$InvokeDynamicInsnConvertingMethodVisitor.backportLambda(LambdaUsageBackporter.java:153)
     [exec]     at net.orfjackal.retrolambda.LambdaUsageBackporter$InvokeDynamicInsnConvertingMethodVisitor.visitInvokeDynamicInsn(LambdaUsageBackporter.java:142)
     [exec]     at org.objectweb.asm.ClassReader.readCode(ClassReader.java:1439)
     [exec]     at org.objectweb.asm.ClassReader.readMethod(ClassReader.java:1017)
     [exec]     at org.objectweb.asm.ClassReader.accept(ClassReader.java:693)
     [exec]     at org.objectweb.asm.ClassReader.accept(ClassReader.java:506)
     [exec]     at net.orfjackal.retrolambda.LambdaUsageBackporter.transform(LambdaUsageBackporter.java:26)
     [exec]     at net.orfjackal.retrolambda.Retrolambda$1.transform(Retrolambda.java:42)
     [exec]     at net.orfjackal.retrolambda.BytecodeTransformingFileVisitor.visitFile(BytecodeTransformingFileVisitor.java:25)
     [exec]     at net.orfjackal.retrolambda.BytecodeTransformingFileVisitor.visitFile(BytecodeTransformingFileVisitor.java:11)
     [exec]     at java.nio.file.Files.walkFileTree(Files.java:2670)
     [exec]     at java.nio.file.Files.walkFileTree(Files.java:2742)
     [exec]     at net.orfjackal.retrolambda.Retrolambda.visitFiles(Retrolambda.java:52)
     [exec]     at net.orfjackal.retrolambda.Retrolambda.run(Retrolambda.java:39)
     [exec]     at net.orfjackal.retrolambda.Main.main(Main.java:26)

Does this patch support the use of 3rd-party interfaces with default methods? How about using them as lambdas? That might explain the above failure.

return tmp;
}

static int getReturnIns(Type arg) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The methods getReturnIns and getVarIns can be replaced with org.objectweb.asm.Type#getOpcode

@luontola luontola mentioned this pull request Aug 25, 2014
@@ -52,7 +52,7 @@
</execution>
</executions>
<configuration>
<minimizeJar>true</minimizeJar>
<!-- <minimizeJar>true</minimizeJar> --> <!-- http://jira.codehaus.org/browse/MSHADE-174 -->
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be possible to re-enable minimizeJar after this is merged with master, because the latest Retrolambda backports itself to Java 6.

@luontola
Copy link
Owner

I've committed IntelliJ IDEA's code style settings to master. Please reformat your code with them (or at least use indent of 4 spaces).

@luontola luontola changed the title Try this out Default methods Aug 25, 2014
@Arneball
Copy link
Contributor Author

It will not process library interfaces right now. And i wonder how it would
be done. If we find a reference to a interface with default methods, should
we rewrite that interface also and put it to the output-path for processed
classes? What will happen when we try to load java.util.Interface at
runtime if we have a processed one in the the classpath and the original in
the boot class path for example?
But i also wonder how you can run retrolambda itself with java6 since you
use java7 apis.

2014-08-25 18:01 GMT+02:00 Esko Luontola notifications@github.com:

This fails when merged with master. The version in master processes
Retrolambda with itself, so that the Maven plugin (which is Java 6
compatible) can use Retrolambda directly.

[INFO] --- maven-antrun-plugin:1.7:run (retrolambda-inception) @ retrolambda ---
[INFO] Executing tasks

main:
[exec] Retrolambda DEVELOPMENT-VERSION
[exec] Bytecode version: 50 (Java 6)
[exec] Input directory: C:\DEVEL\Retrolambda\retrolambda\retrolambda\target\classes
[exec] Output directory: C:\DEVEL\Retrolambda\retrolambda\retrolambda\target\classes
[exec] Classpath: C:\DEVEL\Retrolambda\retrolambda\retrolambda\target\classes;C:\Users\ORFJackal.m2\repository\org\ow2\asm\asm-debug-all\5.0.2\asm-debug-all-5.0.2.jar
[exec] Visiting interface net/orfjackal/retrolambda/BytecodeTransformingFileVisitor
[exec] Class is net/orfjackal/retrolambda/BytecodeTransformingFileVisitor, non abstract true, Interfaces are [], default methods are []
[exec] Visiting interface net/orfjackal/retrolambda/Config
[exec] Class is net/orfjackal/retrolambda/Config, non abstract true, Interfaces are [], default methods are []
[exec] Saving lambda class: net/orfjackal/retrolambda/Config$$Lambda$1
[exec] Interface: java/util/function/Predicate, methods: [public abstract boolean java.util.function.Predicate.test(java.lang.Object), public default java.util.function.Predicate java.util.function.Predicate.and(java.util.function.Predicate), public default java.util.function.Predicate java.util.function.Predicate.or(java.util.function.Predicate), public static java.util.function.Predicate java.util.function.Predicate.isEqual(java.lang.Object), public default java.util.function.Predicate java.util.function.Predicate.negate()]
[exec] NEED TO CREATE PROXY TO java/util/function/Predicatenull
[exec] interface java.util.function.Predicate
[exec] NEED TO CREATE PROXY TO java/util/function/Predicatenull
[exec] interface java.util.function.Predicate
[exec] NEED TO CREATE PROXY TO java/util/function/Predicatenull
[exec] interface java.util.function.Predicate
[exec] NEED TO CREATE PROXY TO java/util/function/Predicatenull
[exec] interface java.util.function.Predicate
[exec] Class is net/orfjackal/retrolambda/Config$$Lambda$1, non abstract true, Interfaces are [java/util/function/Predicate], default methods are [MethodContainer{methodName='or', methodDesc='(Ljava/util/function/Predicate;)Ljava/util/function/Predicate;', interfce='java/util/function/Predicate', signature='null', exceptions=[]}, MethodContainer{methodName='isEqual', methodDesc='(Ljava/lang/Object;)Ljava/util/function/Predicate;', interfce='java/util/function/Predicate', signature='null', exceptions=[]}, MethodContainer{methodName='negate', methodDesc='()Ljava/util/function/Predicate;', interfce='java/util/function/Predicate', signature='null', exceptions=[]}, MethodContainer{methodName='and', methodDesc='(Ljava/util/function/Predicate;)Ljava/util/function/Predicate;', interfce='java/util/function/Predicate', signature='null', exceptions=[]}]
[exec] VISITEND, CREATING PROXY MethodContainer{methodName='or', methodDesc='(Ljava/util/function/Predicate;)Ljava/util/function/Predicate;', interfce='java/util/function/Predicate', signature='null', exceptions=[]}
[exec] Find right interfaces for MethodContainer{methodName='or', methodDesc='(Ljava/util/function/Predicate;)Ljava/util/function/Predicate;', interfce='java/util/function/Predicate', signature='null', exceptions=[]} [java/util/function/Predicate]
[exec] It thinks that the right interface is java/util/function/Predicate
[exec] VISITEND, CREATING PROXY MethodContainer{methodName='isEqual', methodDesc='(Ljava/lang/Object;)Ljava/util/function/Predicate;', interfce='java/util/function/Predicate', signature='null', exceptions=[]}
[exec] Find right interfaces for MethodContainer{methodName='isEqual', methodDesc='(Ljava/lang/Object;)Ljava/util/function/Predicate;', interfce='java/util/function/Predicate', signature='null', exceptions=[]} [java/util/function/Predicate]
[exec] ERROR: Failed to backport lambda class: net/orfjackal/retrolambda/Config$$Lambda$1
[exec] java.lang.NullPointerException
[exec] at net.orfjackal.retrolambda.defaultmethods.ClassModifier$$Lambda$11/1721931908.get(Unknown Source)
[exec] at java.util.Optional.orElseThrow(Optional.java:290)
[exec] at net.orfjackal.retrolambda.defaultmethods.ClassModifier.findRightInterace(ClassModifier.java:128)
[exec] at net.orfjackal.retrolambda.defaultmethods.ClassModifier.visitEnd(ClassModifier.java:95)
[exec] at org.objectweb.asm.ClassVisitor.visitEnd(ClassVisitor.java:317)
[exec] at net.orfjackal.retrolambda.LambdaClassBackporter$LambdaClassVisitor.visitEnd(LambdaClassBackporter.java:73)
[exec] at org.objectweb.asm.ClassReader.accept(ClassReader.java:697)
[exec] at org.objectweb.asm.ClassReader.accept(ClassReader.java:506)
[exec] at net.orfjackal.retrolambda.LambdaClassBackporter.transform(LambdaClassBackporter.java:22)
[exec] at net.orfjackal.retrolambda.LambdaClassSaver.reifyLambdaClass(LambdaClassSaver.java:28)
[exec] at net.orfjackal.retrolambda.LambdaClassSaver.saveIfLambda(LambdaClassSaver.java:21)
[exec] at net.orfjackal.retrolambda.LambdaClassDumper$ClassChannel.close(LambdaClassDumper.java:144)
[exec] at java.nio.channels.Channels$1.close(Channels.java:178)
[exec] at java.nio.file.Files.write(Files.java:3300)
[exec] at java.lang.invoke.ProxyClassesDumper.dumpClass(ProxyClassesDumper.java:140)
[exec] at java.lang.invoke.InnerClassLambdaMetafactory$2.run(InnerClassLambdaMetafactory.java:315)
[exec] at java.lang.invoke.InnerClassLambdaMetafactory$2.run(InnerClassLambdaMetafactory.java:312)
[exec] at java.security.AccessController.doPrivileged(Native Method)
[exec] at java.security.AccessController.doPrivileged(AccessController.java:428)
[exec] at java.lang.invoke.InnerClassLambdaMetafactory.spinInnerClass(InnerClassLambdaMetafactory.java:312)
[exec] at java.lang.invoke.InnerClassLambdaMetafactory.buildCallSite(InnerClassLambdaMetafactory.java:194)
[exec] at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:304)
[exec] at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:636)
[exec] at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:658)
[exec] at net.orfjackal.retrolambda.LambdaReifier.callBootstrapMethod(LambdaReifier.java:110)
[exec] at net.orfjackal.retrolambda.LambdaReifier.reifyLambdaClass(LambdaReifier.java:37)
[exec] at net.orfjackal.retrolambda.LambdaUsageBackporter$InvokeDynamicInsnConvertingMethodVisitor.backportLambda(LambdaUsageBackporter.java:153)
[exec] at net.orfjackal.retrolambda.LambdaUsageBackporter$InvokeDynamicInsnConvertingMethodVisitor.visitInvokeDynamicInsn(LambdaUsageBackporter.java:142)
[exec] at org.objectweb.asm.ClassReader.readCode(ClassReader.java:1439)
[exec] at org.objectweb.asm.ClassReader.readMethod(ClassReader.java:1017)
[exec] at org.objectweb.asm.ClassReader.accept(ClassReader.java:693)
[exec] at org.objectweb.asm.ClassReader.accept(ClassReader.java:506)
[exec] at net.orfjackal.retrolambda.LambdaUsageBackporter.transform(LambdaUsageBackporter.java:26)
[exec] at net.orfjackal.retrolambda.Retrolambda$1.transform(Retrolambda.java:42)
[exec] at net.orfjackal.retrolambda.BytecodeTransformingFileVisitor.visitFile(BytecodeTransformingFileVisitor.java:25)
[exec] at net.orfjackal.retrolambda.BytecodeTransformingFileVisitor.visitFile(BytecodeTransformingFileVisitor.java:11)
[exec] at java.nio.file.Files.walkFileTree(Files.java:2670)
[exec] at java.nio.file.Files.walkFileTree(Files.java:2742)
[exec] at net.orfjackal.retrolambda.Retrolambda.visitFiles(Retrolambda.java:52)
[exec] at net.orfjackal.retrolambda.Retrolambda.run(Retrolambda.java:39)
[exec] at net.orfjackal.retrolambda.Main.main(Main.java:26)

Does this patch support the use of 3rd-party interfaces with default
methods? How about using them as lambdas? That might explain the above
failure.


Reply to this email directly or view it on GitHub
#30 (comment).

@luontola
Copy link
Owner

It should just ignore library interfaces, because it won't be able to add methods to library interfaces. Especially it's impossible to mask classes in the java.* packages, because the JVM disallows those packages in the user classpath. The program will then at runtime use an older version of for example java.lang.Iterable, which had a bunch of default methods added in Java 8. (Later we can consider copying the default method implementations to the classes, but that might cause more problems than it solves, and anyways nobody can call the method implementation through the interface unless the interface also has the method.)

Retrolambda's main method will exit if it's not running under Java 8 and also the Maven plugin will not try running Retrolambda if Maven is not running under Java 8. The Maven plugin just needs to be compilable against Retrolambda, so that we don't have to use reflection.

@luontola
Copy link
Owner

Also it's a good benchmark that Retrolambda can backport itself, because it uses lambdas and quite many Java 8 APIs. :)

@luontola
Copy link
Owner

luontola commented Sep 3, 2014

I pulled these commits to the https://github.com/orfjackal/retrolambda/tree/default-methods branch and adjusted the code style for DefaultMethodsTest. I'll do some bigger refactoring on the tests a bit later.

@luontola luontola mentioned this pull request Sep 3, 2014
@luontola
Copy link
Owner

luontola commented Sep 3, 2014

Seems that this pull request is not working even before merging it with master. This happens on OS X.

[INFO] --- retrolambda-maven-plugin:1.5.1-SNAPSHOT:process-test (default) @ end-to-end-tests ---
[INFO] Retrieving Retrolambda 1.5.1-SNAPSHOT
[INFO] Configured Artifact: net.orfjackal.retrolambda:retrolambda:1.5.1-SNAPSHOT:jar
[INFO] Copying retrolambda-1.5.1-SNAPSHOT.jar to /Users/eskolu/Development/retrolambda/end-to-end-tests/target/retrolambda/retrolambda.jar
[INFO] Processing classes with Retrolambda
[INFO] Toolchain in retrolambda-maven-plugin: JDK[/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home]
[INFO] Executing tasks

main:
     [exec] objc[76562]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/bin/java and /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined.
     [exec] Retrolambda 1.5.1-SNAPSHOT
     [exec] Bytecode version: 51 (Java 7)
     [exec] Input directory:  /Users/eskolu/Development/retrolambda/end-to-end-tests/target/test-classes
     [exec] Output directory: /Users/eskolu/Development/retrolambda/end-to-end-tests/target/test-classes
     [exec] Classpath:        /Users/eskolu/Development/retrolambda/end-to-end-tests/target/test-classes:/Users/eskolu/Development/retrolambda/end-to-end-tests/target/classes:/Users/eskolu/.m2/repository/com/google/guava/guava/11.0.2/guava-11.0.2.jar:/Users/eskolu/.m2/repository/com/google/code/findbugs/jsr305/1.3.9/jsr305-1.3.9.jar:/Users/eskolu/.m2/repository/junit/junit/4.11/junit-4.11.jar:/Users/eskolu/.m2/repository/org/hamcrest/hamcrest-library/1.3/hamcrest-library-1.3.jar:/Users/eskolu/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar:/Users/eskolu/.m2/repository/org/mockito/mockito-core/1.9.5/mockito-core-1.9.5.jar:/Users/eskolu/.m2/repository/org/objenesis/objenesis/1.0/objenesis-1.0.jar
     [exec] Visiting interface net/orfjackal/retrolambda/test/ClasspathTest
     [exec] Class is net/orfjackal/retrolambda/test/ClasspathTest, non abstract true, Interfaces are [], default methods are []
     [exec] Saving lambda class: net/orfjackal/retrolambda/test/ClasspathTest$$Lambda$2
     [exec] Interface: org/hamcrest/SelfDescribing, methods: [public abstract void org.hamcrest.SelfDescribing.describeTo(org.hamcrest.Description)]
     [exec] Class is net/orfjackal/retrolambda/test/ClasspathTest$$Lambda$2, non abstract true, Interfaces are [org/hamcrest/SelfDescribing], default methods are []
     [exec] Visiting interface net/orfjackal/retrolambda/test/DefaultMethodsTest$1
     [exec] Interface: net/orfjackal/retrolambda/test/DefaultMethodsTest$Child2, methods: [public default java.lang.String net.orfjackal.retrolambda.test.DefaultMethodsTest$Child2.method(), public default java.lang.Object net.orfjackal.retrolambda.test.DefaultMethodsTest$Child2.method()]
     [exec] NEED TO CREATE PROXY TO net/orfjackal/retrolambda/test/DefaultMethodsTest$Child2null
     [exec] interface net.orfjackal.retrolambda.test.DefaultMethodsTest$Child2
     [exec] NEED TO CREATE PROXY TO net/orfjackal/retrolambda/test/DefaultMethodsTest$Child2null
     [exec] interface net.orfjackal.retrolambda.test.DefaultMethodsTest$Child2
     [exec] Class is net/orfjackal/retrolambda/test/DefaultMethodsTest$1, non abstract true, Interfaces are [net/orfjackal/retrolambda/test/DefaultMethodsTest$Child2], default methods are [MethodContainer{methodName='method', methodDesc='()Ljava/lang/String;', interfce='net/orfjackal/retrolambda/test/DefaultMethodsTest$Child2', signature='null', exceptions=[]}, MethodContainer{methodName='method', methodDesc='()Ljava/lang/Object;', interfce='net/orfjackal/retrolambda/test/DefaultMethodsTest$Child2', signature='null', exceptions=[]}]
     [exec] VISITEND, CREATING PROXY MethodContainer{methodName='method', methodDesc='()Ljava/lang/String;', interfce='net/orfjackal/retrolambda/test/DefaultMethodsTest$Child2', signature='null', exceptions=[]}
     [exec] Find right interfaces for MethodContainer{methodName='method', methodDesc='()Ljava/lang/String;', interfce='net/orfjackal/retrolambda/test/DefaultMethodsTest$Child2', signature='null', exceptions=[]} [net/orfjackal/retrolambda/test/DefaultMethodsTest$Child2]
     [exec] Error! Failed to transform some classes
     [exec] java.lang.BootstrapMethodError: call site initialization exception
     [exec]     at java.lang.invoke.CallSite.makeSite(CallSite.java:298)
     [exec]     at java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:294)
     [exec]     at net.orfjackal.retrolambda.defaultmethods.ClassModifier.findRightInterace(ClassModifier.java:118)
     [exec]     at net.orfjackal.retrolambda.defaultmethods.ClassModifier.visitEnd(ClassModifier.java:95)
     [exec]     at net.orfjackal.retrolambda.asm.ClassVisitor.visitEnd(ClassVisitor.java:317)
     [exec]     at net.orfjackal.retrolambda.defaultmethods.InterfaceModifier.visitEnd(InterfaceModifier.java:81)
     [exec]     at net.orfjackal.retrolambda.asm.ClassVisitor.visitEnd(ClassVisitor.java:317)
     [exec]     at net.orfjackal.retrolambda.LambdaUsageBackporter$InvokeDynamicInsnConverter.visitEnd(LambdaUsageBackporter.java:112)
     [exec]     at net.orfjackal.retrolambda.asm.ClassReader.accept(ClassReader.java:697)
     [exec]     at net.orfjackal.retrolambda.asm.ClassReader.accept(ClassReader.java:506)
     [exec]     at net.orfjackal.retrolambda.LambdaUsageBackporter.transform(LambdaUsageBackporter.java:26)
     [exec]     at net.orfjackal.retrolambda.Main$1.transform(Main.java:46)
     [exec]     at net.orfjackal.retrolambda.BytecodeTransformingFileVisitor.visitFile(BytecodeTransformingFileVisitor.java:25)
     [exec]     at net.orfjackal.retrolambda.BytecodeTransformingFileVisitor.visitFile(BytecodeTransformingFileVisitor.java:11)
     [exec]     at java.nio.file.Files.walkFileTree(Files.java:2630)
     [exec]     at java.nio.file.Files.walkFileTree(Files.java:2702)
     [exec]     at net.orfjackal.retrolambda.Main.visitFiles(Main.java:60)
     [exec]     at net.orfjackal.retrolambda.Main.main(Main.java:43)
     [exec] Caused by: java.lang.LinkageError: loader (instance of  sun/misc/Launcher$AppClassLoader): attempted  duplicate class definition for name: "net/orfjackal/retrolambda/defaultmethods/ClassModifier$$Lambda$1"
     [exec]     at sun.misc.Unsafe.defineClass(Native Method)
     [exec]     at java.lang.invoke.InnerClassLambdaMetafactory.spinInnerClass(InnerClassLambdaMetafactory.java:286)
     [exec]     at java.lang.invoke.InnerClassLambdaMetafactory.buildCallSite(InnerClassLambdaMetafactory.java:169)
     [exec]     at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:215)
     [exec]     at java.lang.invoke.CallSite.makeSite(CallSite.java:283)
     [exec]     ... 17 more

@Arneball
Copy link
Contributor Author

Arneball commented Sep 4, 2014

Strange. I did development on osx, unfortunately i've been busy for a
couple of weeks, but i'll try to look into this. I have a concern though
about how to find interface classes. Right now we have a class loader like
inputDir ++ otherClassPaths. When we look for classes and interfaces to
transform we search in that class loader for interfaces for the classes
being transformed. We should only look in inputDir for those interfaces and
if those interfaces extends otherClassPath interfaces we shouldn't
transform them unless the subclassed interfaces introduces default methods
themselves?

Do you have any input on how to handle this case? Should we introduce
another method loadClass(boolean lookOnlyInInputDir) or something similar?

Best regards
Den 4 sep 2014 00:28 skrev "Esko Luontola" notifications@github.com:

Seems that this pull request is not working even before merging it with
master. This happens on OS X.

[INFO] --- retrolambda-maven-plugin:1.5.1-SNAPSHOT:process-test (default) @ end-to-end-tests ---
[INFO] Retrieving Retrolambda 1.5.1-SNAPSHOT
[INFO] Configured Artifact: net.orfjackal.retrolambda:retrolambda:1.5.1-SNAPSHOT:jar
[INFO] Copying retrolambda-1.5.1-SNAPSHOT.jar to /Users/eskolu/Development/retrolambda/end-to-end-tests/target/retrolambda/retrolambda.jar
[INFO] Processing classes with Retrolambda
[INFO] Toolchain in retrolambda-maven-plugin: JDK[/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home]
[INFO] Executing tasks

main:
[exec] objc[76562]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/bin/java and /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/lib/libinstrument.dylib. One of the two will be used. Which one is undefined.
[exec] Retrolambda 1.5.1-SNAPSHOT
[exec] Bytecode version: 51 (Java 7)
[exec] Input directory: /Users/eskolu/Development/retrolambda/end-to-end-tests/target/test-classes
[exec] Output directory: /Users/eskolu/Development/retrolambda/end-to-end-tests/target/test-classes
[exec] Classpath: /Users/eskolu/Development/retrolambda/end-to-end-tests/target/test-classes:/Users/eskolu/Development/retrolambda/end-to-end-tests/target/classes:/Users/eskolu/.m2/repository/com/google/guava/guava/11.0.2/guava-11.0.2.jar:/Users/eskolu/.m2/repository/com/google/code/findbugs/jsr305/1.3.9/jsr305-1.3.9.jar:/Users/eskolu/.m2/repository/junit/junit/4.11/junit-4.11.jar:/Users/eskolu/.m2/repository/org/hamcrest/hamcrest-library/1.3/hamcrest-library-1.3.jar:/Users/eskolu/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar:/Users/eskolu/.m2/repository/org/mockito/mockito-core/1.9.5/mockito-core-1.9.5.jar:/Users/eskolu/.m2/repository/org/objenesis/objenesis/1.0/objenesis-1.0.jar
[exec] Visiting interface net/orfjackal/retrolambda/test/ClasspathTest
[exec] Class is net/orfjackal/retrolambda/test/ClasspathTest, non abstract true, Interfaces are [], default methods are []
[exec] Saving lambda class: net/orfjackal/retrolambda/test/ClasspathTest$$Lambda$2
[exec] Interface: org/hamcrest/SelfDescribing, methods: [public abstract void org.hamcrest.SelfDescribing.describeTo(org.hamcrest.Description)]
[exec] Class is net/orfjackal/retrolambda/test/ClasspathTest$$Lambda$2, non abstract true, Interfaces are [org/hamcrest/SelfDescribing], default methods are []
[exec] Visiting interface net/orfjackal/retrolambda/test/DefaultMethodsTest$1
[exec] Interface: net/orfjackal/retrolambda/test/DefaultMethodsTest$Child2, methods: [public default java.lang.String net.orfjackal.retrolambda.test.DefaultMethodsTest$Child2.method(), public default java.lang.Object net.orfjackal.retrolambda.test.DefaultMethodsTest$Child2.method()]
[exec] NEED TO CREATE PROXY TO net/orfjackal/retrolambda/test/DefaultMethodsTest$Child2null
[exec] interface net.orfjackal.retrolambda.test.DefaultMethodsTest$Child2
[exec] NEED TO CREATE PROXY TO net/orfjackal/retrolambda/test/DefaultMethodsTest$Child2null
[exec] interface net.orfjackal.retrolambda.test.DefaultMethodsTest$Child2
[exec] Class is net/orfjackal/retrolambda/test/DefaultMethodsTest$1, non abstract true, Interfaces are [net/orfjackal/retrolambda/test/DefaultMethodsTest$Child2], default methods are [MethodContainer{methodName='method', methodDesc='()Ljava/lang/String;', interfce='net/orfjackal/retrolambda/test/DefaultMethodsTest$Child2', signature='null', exceptions=[]}, MethodContainer{methodName='method', methodDesc='()Ljava/lang/Object;', interfce='net/orfjackal/retrolambda/test/DefaultMethodsTest$Child2', signature='null', exceptions=[]}]
[exec] VISITEND, CREATING PROXY MethodContainer{methodName='method', methodDesc='()Ljava/lang/String;', interfce='net/orfjackal/retrolambda/test/DefaultMethodsTest$Child2', signature='null', exceptions=[]}
[exec] Find right interfaces for MethodContainer{methodName='method', methodDesc='()Ljava/lang/String;', interfce='net/orfjackal/retrolambda/test/DefaultMethodsTest$Child2', signature='null', exceptions=[]} [net/orfjackal/retrolambda/test/DefaultMethodsTest$Child2]
[exec] Error! Failed to transform some classes
[exec] java.lang.BootstrapMethodError: call site initialization exception
[exec] at java.lang.invoke.CallSite.makeSite(CallSite.java:298)
[exec] at java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:294)
[exec] at net.orfjackal.retrolambda.defaultmethods.ClassModifier.findRightInterace(ClassModifier.java:118)
[exec] at net.orfjackal.retrolambda.defaultmethods.ClassModifier.visitEnd(ClassModifier.java:95)
[exec] at net.orfjackal.retrolambda.asm.ClassVisitor.visitEnd(ClassVisitor.java:317)
[exec] at net.orfjackal.retrolambda.defaultmethods.InterfaceModifier.visitEnd(InterfaceModifier.java:81)
[exec] at net.orfjackal.retrolambda.asm.ClassVisitor.visitEnd(ClassVisitor.java:317)
[exec] at net.orfjackal.retrolambda.LambdaUsageBackporter$InvokeDynamicInsnConverter.visitEnd(LambdaUsageBackporter.java:112)
[exec] at net.orfjackal.retrolambda.asm.ClassReader.accept(ClassReader.java:697)
[exec] at net.orfjackal.retrolambda.asm.ClassReader.accept(ClassReader.java:506)
[exec] at net.orfjackal.retrolambda.LambdaUsageBackporter.transform(LambdaUsageBackporter.java:26)
[exec] at net.orfjackal.retrolambda.Main$1.transform(Main.java:46)
[exec] at net.orfjackal.retrolambda.BytecodeTransformingFileVisitor.visitFile(BytecodeTransformingFileVisitor.java:25)
[exec] at net.orfjackal.retrolambda.BytecodeTransformingFileVisitor.visitFile(BytecodeTransformingFileVisitor.java:11)
[exec] at java.nio.file.Files.walkFileTree(Files.java:2630)
[exec] at java.nio.file.Files.walkFileTree(Files.java:2702)
[exec] at net.orfjackal.retrolambda.Main.visitFiles(Main.java:60)
[exec] at net.orfjackal.retrolambda.Main.main(Main.java:43)
[exec] Caused by: java.lang.LinkageError: loader (instance of sun/misc/Launcher$AppClassLoader): attempted duplicate class definition for name: "net/orfjackal/retrolambda/defaultmethods/ClassModifier$$Lambda$1"
[exec] at sun.misc.Unsafe.defineClass(Native Method)
[exec] at java.lang.invoke.InnerClassLambdaMetafactory.spinInnerClass(InnerClassLambdaMetafactory.java:286)
[exec] at java.lang.invoke.InnerClassLambdaMetafactory.buildCallSite(InnerClassLambdaMetafactory.java:169)
[exec] at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:215)
[exec] at java.lang.invoke.CallSite.makeSite(CallSite.java:283)
[exec] ... 17 more


Reply to this email directly or view it on GitHub
#30 (comment).

@luontola
Copy link
Owner

luontola commented Sep 4, 2014

The error might be because of something like iterating the classes in different order. File systems can list the files in any order. It's not possible to assume anything about whether the interface or its implementors are discovered first.

@luontola
Copy link
Owner

luontola commented Sep 4, 2014

We should only look in inputDir for those interfaces and
if those interfaces extends otherClassPath interfaces we shouldn't
transform them unless the subclassed interfaces introduces default methods
themselves?

Retrolambda already walks the inputDir file tree. It should backport only the default methods that it finds in the interfaces in that directory.

Since the implementors may be visited before or after the interface they implement, it may be necessary to either (1) first find all the interfaces to backport and after that backport all lambdas, or (2) keep track of what interfaces the already visited classes implement and revisit them after it's discovered that some of the interfaces had default methods. Option 1 seems easier to get right.

@luontola
Copy link
Owner

luontola commented Sep 4, 2014

I've now refactored DefaultMethodsTest and added some more tests. See the commit bc99e75 in the default-methods branch.

@luontola
Copy link
Owner

luontola commented Sep 4, 2014

And now there are still some more tests. I think most of the edge cases are now covered.

Or maybe also the method visibility (in implementing classes) needs some checks... I'll need to check how Java 8 handles those cases - it might not compile, but might still be binary compatible (i.e. implementing class has a non-public method with same signature as a default method that was added to an interface).
Update: It doesn't compile, so Retrolambda doesn't need to handle those cases.

@luontola luontola merged commit 9038a86 into luontola:master Sep 5, 2014
@luontola
Copy link
Owner

luontola commented Sep 5, 2014

I merged this to master using feature toggles. Let's continue discussion at issue #31

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants