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

name mangling vs. java reflection #4316

Open
scabug opened this issue Mar 6, 2011 · 9 comments
Open

name mangling vs. java reflection #4316

scabug opened this issue Mar 6, 2011 · 9 comments
Milestone

Comments

@scabug
Copy link

scabug commented Mar 6, 2011

As of r24390 signatures appear to be in good shape with the exception of this, which I can only document for now. Actually this is not about signatures per se, but names which cause java -Xprint to fail.

class Bippy {
  val quuxVal = () => new AnyRef        // fails
  lazy val quuxLazy = () => new AnyRef  // works
  def quuxDef = () => new AnyRef        // works
}

// Only val excludes the name.
//
// -rw-r--r--   1 paulp  staff   614 Mar  6 12:37 Bippy$$anonfun$1.class
// -rw-r--r--   1 paulp  staff   667 Mar  6 12:37 Bippy$$anonfun$quuxDef$1.class
// -rw-r--r--   1 paulp  staff   670 Mar  6 12:37 Bippy$$anonfun$quuxLazy$1.class
// -rw-r--r--   1 paulp  staff  1340 Mar  6 12:37 Bippy.class
//
// Only val turns up in getClasses, and not anonymously.
// 
// % scala -nocompdaemon -e 'classOf[Bippy].getClasses foreach println'
// class Bippy$$anonfun$1
// % scala -nocompdaemon -e 'classOf[Bippy].getClasses map (_.isAnonymousClass) foreach println'
// false
//
// Only val has a symmetric inner class relationship.
//
// Bippy-side:
// InnerClass: 
//  public final SI-44 of SI-14; //class Bippy$$anonfun$1 of class Bippy
//  public final SI-36; //class Bippy$$anonfun$quuxDef$1
//  public final SI-21; //class Bippy$$anonfun$quuxLazy$1
//
// Closure-side:
// % for file in Bippy\$*.class ; do javap -verbose "${file%.class}" | grep '//class Bippy' ; done
//    public final SI-9 of SI-32; //class Bippy$$anonfun$1 of class Bippy
//    public final SI-9; //class Bippy$$anonfun$quuxDef$1
//    public final SI-9; //class Bippy$$anonfun$quuxLazy$1

Here is the java equivalent of the failing construct:

// Bippy.java 
public class Bippy {
  scala.Function0<Object> quux = new scala.runtime.AbstractFunction0<Object>() {
    public Object apply() {
      return new Object();
    }
  };
}  

In an unsurprising twist, java creates the inner class java is looking for:

InnerClass: 
 SI-2; //class Bippy$1  
% javac7 -cp /scala/inst/29/lib/scala-library.jar:. -Xprint Bippy

public class Bippy {
  scala.Function0<java.lang.Object> quux;

  public Bippy();
}  

The successful output from the lazy val and def cases:

class Bippy {
  // InnerClass: 
  //  public final SI-7; //class Bippy$$anonfun$quux$1  
  def quux = () => new AnyRef
}

@scala.reflect.ScalaSignature(bytes=...)
public class Bippy implements scala.ScalaObject {

  public scala.Function0<java.lang.Object> quux();

  public Bippy();
}

class Bippy {
  // InnerClass: 
  //  public final SI-17; //class Bippy$$anonfun$quux$1
  lazy val quux = () => new AnyRef
}

@scala.reflect.ScalaSignature(bytes=...)
public class Bippy implements scala.ScalaObject {
  private scala.Function0<java.lang.Object> quux;
  public volatile int bitmap$0;

  public scala.Function0<java.lang.Object> quux();

  public Bippy();
}

The failing output from the val case:

% javac7 -cp /scala/inst/29/lib/scala-library.jar:. -Xprint Bippy 
error: cannot access 1
  class file for Bippy$1 not found
1 error
@scabug
Copy link
Author

scabug commented Mar 6, 2011

Imported From: https://issues.scala-lang.org/browse/SI-4316?orig=1
Reporter: @paulp
See #9, #44, #2, #17, #21, #7, #14, #32, #36, #4023, #4912

@scabug
Copy link
Author

scabug commented Mar 8, 2011

@ingoem said:
Do you wanna discuss this at the meeting, Paul? Feel free to reassign.

@scabug
Copy link
Author

scabug commented Aug 13, 2011

@gkossakowski said:
I think I got lost here. Why javac -Xprint is looking for Bippy$1? It seems to be never referenced from anywhere.

@scabug
Copy link
Author

scabug commented Aug 13, 2011

@paulp said:
It's hardcoded in javac. (Take that, implementors.) Such hardcoding is also why e.g. getSimpleName throws an exception for us on nested classes.

@scabug
Copy link
Author

scabug commented Aug 13, 2011

@gkossakowski said:
Do you mean that javac expects that first anonymous class is named 1 (our Outer$1 if we think of full name), second is named 2, etc?

@scabug
Copy link
Author

scabug commented Aug 13, 2011

@paulp said:
Don't hold me to too many details, but yes. It is the reverse which gets us elsewhere: reflection expects a class called foo$bar$baz$1 to be nested inside a class called foo$bar$baz, and with us that's not all that likely.

@scabug
Copy link
Author

scabug commented Aug 13, 2011

@gkossakowski said:
I see. It's interesting, I thought InnerClasses attribute in a class servers exactly this purpose to provide information about nesting. If implementations decided to ignore their own invention and rely on strings then I'd be in favor of ignoring Java reflection entirely.

It's quite likely that we'll be in luxury situation of having native Scala reflection that we can point folks at.

@scabug
Copy link
Author

scabug commented Aug 13, 2011

@soc said:
The problem with Java reflection reminds me of #4023, where it creates problems with "object".

Does someone know the current javac behaviour is defined in the spec?

If not, it would probably make sense to create a ticket in Oracle's bug tracker, even if we can sidestep the problem with Scala reflection, because huge optimizations efforts went into making reflection fast ... so if we can use Java reflection underneath instead of rolling things ourselves, we could benefit from that hard work.

@scabug
Copy link
Author

scabug commented Jul 11, 2012

@dcsobral said:
Interestingly, this issue is related to SI-4024, which is a blocker for Scala reflection...

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

No branches or pull requests

1 participant