sirthias / pegdown

A pure-Java Markdown processor based on a parboiled PEG parser supporting a number of extensions
http://pegdown.org
Apache License 2.0
1.29k stars 218 forks source link

java.lang.ExceptionInInitializerError -> Is this support for Android ? #231

Closed TakWolf closed 8 months ago

TakWolf commented 8 years ago

I do not find an information about Android, do it support ?

When I use pegdown on android, it got a exception :

 private static final PegDownProcessor md = new PegDownProcessor();
 FATAL EXCEPTION: main
Process: org.cnodejs.android.md, PID: 502
java.lang.ExceptionInInitializerError
    at org.cnodejs.android.md.display.activity.MainActivity.updateMessageCountViews(MainActivity.java:486)
    at org.cnodejs.android.md.presenter.implement.MainPresenter$4.onResultOk(MainPresenter.java:119)
    at org.cnodejs.android.md.presenter.implement.MainPresenter$4.onResultOk(MainPresenter.java:114)
    at org.cnodejs.android.md.model.api.CallbackAdapter.onResponse(CallbackAdapter.java:15)
    at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5343)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
 Caused by: java.lang.RuntimeException: Error creating extended parser class: Class not found
    at org.parboiled.Parboiled.createParser(Parboiled.java:58)
    at org.pegdown.PegDownProcessor.<init>(PegDownProcessor.java:94)
    at org.pegdown.PegDownProcessor.<init>(PegDownProcessor.java:73)
    at org.pegdown.PegDownProcessor.<init>(PegDownProcessor.java:54)
    at org.pegdown.PegDownProcessor.<init>(PegDownProcessor.java:47)
    at org.cnodejs.android.md.util.FormatUtils.<clinit>(FormatUtils.java:125)
    at org.cnodejs.android.md.display.activity.MainActivity.updateMessageCountViews(MainActivity.java:486) 
    at org.cnodejs.android.md.presenter.implement.MainPresenter$4.onResultOk(MainPresenter.java:119) 
    at org.cnodejs.android.md.presenter.implement.MainPresenter$4.onResultOk(MainPresenter.java:114) 
    at org.cnodejs.android.md.model.api.CallbackAdapter.onResponse(CallbackAdapter.java:15) 
    at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68) 
    at android.os.Handler.handleCallback(Handler.java:739) 
    at android.os.Handler.dispatchMessage(Handler.java:95) 
    at android.os.Looper.loop(Looper.java:135) 
    at android.app.ActivityThread.main(ActivityThread.java:5343) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:372) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700) 
 Caused by: java.io.IOException: Class not found
    at org.objectweb.asm.ClassReader.a(Unknown Source)
    at org.objectweb.asm.ClassReader.<init>(Unknown Source)
    at org.parboiled.transform.AsmUtils.createClassReader(AsmUtils.java:56)
    at org.parboiled.transform.ClassNodeInitializer.process(ClassNodeInitializer.java:62)
    at org.parboiled.transform.ParserTransformer.extendParserClass(ParserTransformer.java:44)
    at org.parboiled.transform.ParserTransformer.transformParser(ParserTransformer.java:38)
    at org.parboiled.Parboiled.createParser(Parboiled.java:54)
    at org.pegdown.PegDownProcessor.<init>(PegDownProcessor.java:94) 
    at org.pegdown.PegDownProcessor.<init>(PegDownProcessor.java:73) 
    at org.pegdown.PegDownProcessor.<init>(PegDownProcessor.java:54) 
    at org.pegdown.PegDownProcessor.<init>(PegDownProcessor.java:47) 
    at org.cnodejs.android.md.util.FormatUtils.<clinit>(FormatUtils.java:125) 
    at org.cnodejs.android.md.display.activity.MainActivity.updateMessageCountViews(MainActivity.java:486) 
    at org.cnodejs.android.md.presenter.implement.MainPresenter$4.onResultOk(MainPresenter.java:119) 
    at org.cnodejs.android.md.presenter.implement.MainPresenter$4.onResultOk(MainPresenter.java:114) 
    at org.cnodejs.android.md.model.api.CallbackAdapter.onResponse(CallbackAdapter.java:15) 
    at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68) 
    at android.os.Handler.handleCallback(Handler.java:739) 
    at android.os.Handler.dispatchMessage(Handler.java:95) 
    at android.os.Looper.loop(Looper.java:135) 
    at android.app.ActivityThread.main(ActivityThread.java:5343) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:372) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700) 

It seem that the problem is org.objectweb.asm

yhonet commented 8 years ago

I had the same problem: final PegDownProcessor processor = new PegDownProcessor();

AndroidRuntime: FATAL EXCEPTION: 
...
java.lang.RuntimeException: Error creating extended parser class: Class not found
      at org.parboiled.Parboiled.createParser(Parboiled.java:58)
      at org.pegdown.PegDownProcessor.<init>(PegDownProcessor.java:94)
      at org.pegdown.PegDownProcessor.<init>(PegDownProcessor.java:73)
      at org.pegdown.PegDownProcessor.<init>(PegDownProcessor.java:54)
      at org.pegdown.PegDownProcessor.<init>(PegDownProcessor.java:47)
      at ...
   Caused by: java.io.IOException: Class not found
      at org.objectweb.asm.ClassReader.a(Unknown Source)
      at org.objectweb.asm.ClassReader.<init>(Unknown Source)
      at org.parboiled.transform.AsmUtils.createClassReader(AsmUtils.java:56)
      at org.parboiled.transform.ClassNodeInitializer.process(ClassNodeInitializer.java:62)
      at org.parboiled.transform.ParserTransformer.extendParserClass(ParserTransformer.java:44)
      at org.parboiled.transform.ParserTransformer.transformParser(ParserTransformer.java:38)
      at org.parboiled.Parboiled.createParser(Parboiled.java:54)
      at org.pegdown.PegDownProcessor.<init>(PegDownProcessor.java:94) 
      at org.pegdown.PegDownProcessor.<init>(PegDownProcessor.java:73) 
      at org.pegdown.PegDownProcessor.<init>(PegDownProcessor.java:54) 
      at org.pegdown.PegDownProcessor.<init>(PegDownProcessor.java:47) 
      at...
SreenuAndroid commented 7 years ago

I too have the same problem

LeadroyaL commented 7 years ago

same to me thanks~~

Miha-x64 commented 7 years ago

Seems that ASM can't transform classes on Android because they have different format. PegDownProcessor has another constructor that accepts Parser, we should try creating parser ourselves without ASM. I've tried reproducing conditions that had originally been achieved by using ASM:

/* Kotlin */
val parser =
        Parser(
                Extensions.NONE,
                PegDownProcessor.DEFAULT_MAX_PARSING_TIME,
                Parser.DefaultParseRunnerProvider,
                PegDownPlugins.NONE)
val matcher = SequenceMatcher(Array<Rule?>(0, { null /* original object has an instance of dynamically generated class here */ }))
parser.context = MatcherContext(
        DefaultInputBuffer(chars),
        DefaultValueStack<Any>(),
        ArrayList<ParseError>(),
        BasicParseRunner<Any>(matcher),
        matcher,
        true)
return PegDownProcessor(parser)

But now I'm getting org.parboiled.errors.GrammarException: Illegal call to getMatch(), getMatchStartIndex(), getMatchEndIndex() or getMatchRange(), only valid in Sequence rule actions that are not in first position.

fiskurgit commented 7 years ago

To enable Android support someone's going to have to look at adding a configuration to use ASMDEX instead of ASM: http://asm.ow2.org/doc/tutorial-asmdex.html

vsch commented 7 years ago

If you need android support it is probably easier to switch to another parser rather than trying to wrestle with pegdown.

commonmark-java is an excellent choice if you don't need source element based AST (it generates output based AST), don't need a lot of extensions and can work with CommonMark markdown format https://github.com/atlassian/commonmark-java, Java 1.7 and android compatible.

I rewrote commonmark-java to replace pegdown in my Markdown Navigator plugin for IntelliJ IDEs: https://github.com/vsch/idea-multimarkdown. The parser project is https://github.com/vsch/flexmark-java. It has very detailed source based AST with source offset for every part of the element. I need that for syntax highlighting and other plugin source reliant features.

It is CommonMark 0.27 (GitHub Comments) compliant but has parser configuration options to emulate list indentation rules used by: markdown.pl, MultiMarkdown (like pegdown 4 space indents) and kramdown (GitHub Docs). The only extensions that pegdown has that I did not yet implement are: typographic quotes, smarts and definition lists. The rest of the extensions are available, with some extra ones that pegdown does not have.

As an added bonus and what motivated me to switch the parsing is 30-50x faster than pegdown on average documents and several thousand times faster on pegdown's pathological input like [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[.

Right now it is Java language level 1.8 because I used lambda syntax but if you are interested in having it support android I can refactor all the 1.8 constructs to downgrade it to 1.7 for android compatibility or just convert it to Kotlin then can have even better syntax and Java 1.6 compatibility.