Connot find bytecode for class XXX

239 views
Skip to first unread message

Simone Tripodi

unread,
Nov 24, 2010, 8:33:16 AM11/24/10
to google...@googlegroups.com
Hi all guys,
I need to bind a Provider generated by ASM with injection points
generated on the fly, everything gone fine until injection points
resolution by Guice, and got the errors below; I tried to hack the
com.google.inject.internal.MapMaker class loader, adding the new class
definition, but without success.
Does someone know how guice resolved that issue when enhancing the
classes with AOP?
Many thanks in advance, have a nice day!
Simo

com.google.inject.internal.ComputationException:
java.lang.IllegalArgumentException: Cannot find bytecode for class
org.mybatis.guice.datasource.helper.FormattedProvider
at com.google.inject.internal.MapMaker$StrategyImpl.compute(MapMaker.java:553)
at com.google.inject.internal.MapMaker$StrategyImpl.compute(MapMaker.java:419)
at com.google.inject.internal.CustomConcurrentHashMap$ComputingImpl.get(CustomConcurrentHashMap.java:2041)
at com.google.inject.internal.StackTraceElements.forMember(StackTraceElements.java:53)
at com.google.inject.internal.Errors.formatInjectionPoint(Errors.java:635)
at com.google.inject.internal.Errors.formatSource(Errors.java:597)
at com.google.inject.internal.Errors.format(Errors.java:474)
at com.google.inject.CreationException.getMessage(CreationException.java:48)
at java.lang.Throwable.getLocalizedMessage(Throwable.java:267)
at java.lang.Throwable.toString(Throwable.java:344)
at java.lang.String.valueOf(String.java:2615)
at java.io.PrintWriter.print(PrintWriter.java:546)
at java.io.PrintWriter.println(PrintWriter.java:683)
at java.lang.Throwable.printStackTrace(Throwable.java:510)
at org.junit.runner.notification.Failure.getTrace(Failure.java:65)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestListener.testFailure(JUnit4TestListener.java:68)
at org.junit.runner.notification.RunNotifier$4.notifyListener(RunNotifier.java:100)
at org.junit.runner.notification.RunNotifier$SafeNotifier.run(RunNotifier.java:41)
at org.junit.runner.notification.RunNotifier.fireTestFailure(RunNotifier.java:97)
at org.junit.internal.runners.ErrorReportingRunner.runCause(ErrorReportingRunner.java:57)
at org.junit.internal.runners.ErrorReportingRunner.run(ErrorReportingRunner.java:34)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.IllegalArgumentException: Cannot find bytecode
for class org.mybatis.guice.datasource.helper.FormattedProvider
at com.google.inject.internal.Preconditions.checkArgument(Preconditions.java:113)
at com.google.inject.internal.LineNumbers.<init>(LineNumbers.java:57)
at com.google.inject.internal.StackTraceElements$1.apply(StackTraceElements.java:36)
at com.google.inject.internal.StackTraceElements$1.apply(StackTraceElements.java:33)
at com.google.inject.internal.MapMaker$StrategyImpl.compute(MapMaker.java:549)
... 26 more

http://people.apache.org/~simonetripodi/
http://www.99soft.org/

Stuart McCulloch

unread,
Nov 24, 2010, 8:55:14 AM11/24/10
to google...@googlegroups.com
On 24 November 2010 13:33, Simone Tripodi <simone....@gmail.com> wrote:
Hi all guys,
I need to bind a Provider generated by ASM with injection points
generated on the fly, everything gone fine until injection points
resolution by Guice, and got the errors below; I tried to hack the
com.google.inject.internal.MapMaker class loader, adding the new class
definition, but without success.

it's not an issue with MapMaker as such, but the Guice LineNumbers utility
that attempts to supply meaningful source locations for debugging bindings

  public LineNumbers(Class type) throws IOException {
    this.type = type;

    if (!type.isArray()) {
      InputStream in = type.getResourceAsStream("/" + type.getName().replace('.', '/') + ".class");
      Preconditions.checkArgument(in != null, "Cannot find bytecode for %s", type);
      new ClassReader(in).accept(new LineNumberReader(), ClassReader.SKIP_FRAMES);
    }
  }

^ this expects to find a class resource - but of course if you're generating
the provider class completely from scratch with ASM then it won't exist :/

to workaround this issue you could supply your own source when binding
your generated provider - this should then bypass the LineNumber code:

  Binder generatedCodeBinder = binder.withSource( "[generated]" );

  generatedCodeBinder.bind( ...etc...

HTH

Does someone know how guice resolved that issue when enhancing the
classes with AOP?

it's not an issue with Guice's internal AOP because that's applied on top
of classes already registered with the injector - so the LineNumbers code
never has to handle internal proxies
 

--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.




--
Cheers, Stuart

Simone Tripodi

unread,
Nov 24, 2010, 8:56:05 AM11/24/10
to google...@googlegroups.com
Found the reason on com.google.inject.internal.util.LineNumbers
constructor, as shown below.
I immagine you had your good reasons to add this restriction, but in
that way Guice is not able at all to load components created
dynamically via ASM :(


public LineNumbers(Class type) throws IOException {
this.type = type;

if (!type.isArray()) {
InputStream in = type.getResourceAsStream("/" +
type.getName().replace('.', '/') + ".class");
Preconditions.checkArgument(in != null, "Cannot find bytecode
for %s", type);
new ClassReader(in).accept(new LineNumberReader(),
ClassReader.SKIP_FRAMES);
}
}

http://people.apache.org/~simonetripodi/
http://www.99soft.org/

Simone Tripodi

unread,
Nov 24, 2010, 8:58:11 AM11/24/10
to google...@googlegroups.com
Hi Stuart!!! :)
I received your reply just after a second I reposted :)
Thanks a lot for your suggestions, I'll try do follow them as well!!!
Simo

http://people.apache.org/~simonetripodi/
http://www.99soft.org/

Stuart McCulloch

unread,
Nov 24, 2010, 9:00:50 AM11/24/10
to google...@googlegroups.com
On 24 November 2010 13:58, Simone Tripodi <simone....@gmail.com> wrote:
Hi Stuart!!! :)
I received your reply just after a second I reposted :)
Thanks a lot for your suggestions, I'll try do follow them as well!!!

cool - could you also raise an issue over at http://code.google.com/p/google-guice/issues/list to track this?

--
Cheers, Stuart

Simone Tripodi

unread,
Nov 24, 2010, 9:02:38 AM11/24/10
to google...@googlegroups.com
Sure, going to open it now!
Thanks for your support :)
Simo

http://people.apache.org/~simonetripodi/
http://www.99soft.org/

Simone Tripodi

unread,
Nov 24, 2010, 9:12:28 AM11/24/10
to google...@googlegroups.com

Simone Tripodi

unread,
Nov 24, 2010, 9:37:03 AM11/24/10
to google...@googlegroups.com
Hi again Stuart,
sorry for the silly question but I tried following your suggestion:

try {
Provider<XXX> myProvider = MyProviderFactory.newProvider(
[some input] ); // that's the component that uses AMS to generate
components on the fly
Binder childBinder = binder.withSource(myProvider);
childBinder.bind(XXX.class).toProvider(myProvider);
} catch (Exception e) {
binder.addError(e);
}

and throws the same exception. What did I do wrong?
Many thanks in advance,
Simo

http://people.apache.org/~simonetripodi/
http://www.99soft.org/

On Wed, Nov 24, 2010 at 3:12 PM, Simone Tripodi

Stuart McCulloch

unread,
Nov 24, 2010, 9:49:33 AM11/24/10
to google...@googlegroups.com
On 24 November 2010 14:37, Simone Tripodi <simone....@gmail.com> wrote:
Hi again Stuart,
sorry for the silly question but I tried following your suggestion:

       try {
           Provider<XXX> myProvider = MyProviderFactory.newProvider(
[some input] ); // that's the component that uses AMS to generate
components on the fly
           Binder childBinder = binder.withSource(myProvider);
           childBinder.bind(XXX.class).toProvider(myProvider);
       } catch (Exception e) {
           binder.addError(e);
       }

and throws the same exception. What did I do wrong?

using  withSource(myProvider)  will indeed cause the same error as before, because class sources are also processed with LineNumbers

instead you should use something like  withSource("[generated]")  which shouldn't activate the LineNumber code as it's just a plain string



--
Cheers, Stuart

Simone Tripodi

unread,
Nov 24, 2010, 9:57:57 AM11/24/10
to google...@googlegroups.com
Thanks for the hint, sorry if I didn't catch the first time, I thought
"[generated]" was a placeholder :P
BTW, just tried, but without success :(

try {
Binder childBinder = binder.withSource("[generated]");

Provider<XXX> myProvider = MyProviderFactory.newProvider(
[some input] ); // that's the component that uses AMS to generate
components on the fly

childBinder.bind(XXX.class).toProvider(myProvider);
} catch (Exception e) {
binder.addError(e);
}

http://people.apache.org/~simonetripodi/
http://www.99soft.org/

Reply all
Reply to author
Forward
0 new messages