[rules-dev] Accessing Drools compiled classes

Guillaume Sauthier guillaume.sauthier at ow2.org
Wed Nov 3 06:11:09 EDT 2010



Le 02/11/2010 23:29, Mark Proctor a écrit :
> On 02/11/2010 11:02, Guillaume Sauthier wrote:
>> Hi Mark
>> It's nice to have your view on the this subject (even if it 
>> disassemble my current plan ;) )
>>
>> Le 28/10/2010 18:17, Mark Proctor a écrit :
>>> I actually want to move away from compile time generated bytecode 
>>> inside
>>> of the packages. Instead I want to move to just keeping validated
>>> Strings that can be executed via MVEL. Additional we would use ASM to
>>> bytecode compile often used strings at runtime.
>>
>> Isn't it the role of the MVEL Optimizers (I've read they have 
>> something based on ASM) ?
>> BTW, are theses classes generated when rule Package are compiled ?
> I'm actually implementing this as an MVEL optimisation. At the moment 
> MVEL only ASM's setters and getters. I want full "flat" code 
> generation so effectively the generated code is standalone, even if it 
> was generated from mvel. There is no ETA for this.

"flat" code generation ?

>>
>>> So I think giving you direct access to generated bytecode would be a 
>>> bad
>>> thing, it's internal and unstable and you can be sure we'll change 
>>> it as
>>> we want.
>>
>> In a way, I don't care of what is inside the bytecode.
>> I'm only giving it to a bytecode parsing tool (aQute's Bnd) that will 
>> see what needs to be imported. So if there is some bytecode, I'm 
>> happy. if you change what code is generated, that will not affect me 
>> because Bnd will see that the imports have changed and will construct 
>> the bundle's manifest appropriately.
>>
>> I only need the bytecode (and an API to get them cleanly ;) ).
> Get BND to accept a String of imports, and write an ant utility to 
> extract them from Drools.

That's also doable

>>
>>> What you want is to ensure that certain types are imported so Drools 
>>> can
>>> see them, right?
>> Yes, I want to ensure that generated classes in the bundle have all 
>> their imports/requirements fulfilled.
>>> So instead we should be looking at some sort of
>>> analysis tool to provide this, we sort of have this already, but it
>>> won't be complete for your purposes but can be extended. So it tells 
>>> you
>>> want classes are used and were, and you can use the drl parser to
>>> extract imports etc.
>>
>> Can you give me some pointer(s) on what Drools currently have ?
> The Drools DRL parser produces a Descr model of classes that provides 
> things like imports.

OK I see this structure.

One question (again):
Does thes imports are reflecting all the real imports of the generated 
classes ?
I mean, it's kind of obvious that they reflect the imports we place in 
the drl files, but do they also have internal imports?

For example, I've seen that there are some mvel templates that seems to 
be used to be generate the code ("javaInvokers.mvel" for example). 
Theses templates are using classes that are not directly part of the 
rule description but are required to hook up the generated code within 
drools:

@declare{"getMethodBytecode"}
     public java.util.List getMethodBytecode() {
         org.drools.core.util.asm.MethodComparator.Tracer visit = new 
org.drools.core.util.asm.MethodComparator.Tracer("@{methodName}");

         java.io.InputStream is = 
getClass().getClassLoader().getResourceAsStream( 
"@{package}.@{ruleClassName}".replace( '.', '/' ) + ".class" );

         java.io.ByteArrayOutputStream bos = new 
java.io.ByteArrayOutputStream();
         byte[] data = new byte[1024];
         int byteCount;
         try {
             while ( (byteCount = is.read( data,
                                  0,
                                  1024 )) > -1 )
             {
                 bos.write(data, 0, byteCount);
             }
         } catch ( java.io.IOException e ) {
             throw new org.drools.RuntimeDroolsException("Unable 
getResourceAsStream for Class '@{ruleClassName}' ");
         }

         org.mvel2.asm.ClassReader classReader = new 
org.mvel2.asm.ClassReader( bos.toByteArray() );
         classReader.accept( visit, org.mvel2.asm.ClassReader.SKIP_DEBUG  );
         org.mvel2.asm.util.TraceMethodVisitor trace = visit.getTrace();
         return trace.getText();
     }
@end{}

This is primarily theses imports (org.drools.core.util.asm for example) 
that I want to discover.


>>
>>> The resouce type you suggest won't work. The generated class is just 
>>> for
>>> the consequence or some aslects of the "when" it is not the entire 
>>> rule,
>>> so in itself is not a complete resource.
>>
>> Sure, a Package stores more than just the bytecode of generated stuff.
>> But I was thinking that if theses pre-compiled classes where already 
>> in the bundle, it was a waste of resources to also have them in the 
>> serialized Package resource...
>>
>>> Plus again I'd rather move
>>> complete away from this pre-compiled concept and more to validated
>>> strings with on the fly generation.
>>
>> Usually, this is this (uncontrolled for OSGi) on-the-fly generation 
>> that cause some harms.
>>
>>> That said there is a need for environments like app-engine which don't
>>> allow runtime bytecode generation and people want the perf boost of
>>> bytecode to have fully pre-compiled rule sets.
>>
>> Theses are good use cases too. Considering that OSGi "don't allow" 
>> runtime bytecode generation :)
>>
>>>   I would consider
>>> something like this, where a .jar has all the pre-compiled rules. 
>>> But we
>>> are a long way from this, first we need to get an ASM rule compiler
>>> working, that can compile a complete rule, then we can look into a full
>>> pre-compiled ruleset.
>>
>> What do you call a full pre-compiled ruleset ?
>> With my limited understanding, I consider an ASM compiler just like 
>> the old java compiler (it's just faster): it's another way to produce 
>> the same thing: executable bytecode.
>> So I don't see how moving from eclipse compiler to ASM will make 
>> things better for me.
> yes I more meant we'll be revisiting how we do compiled stuff in 
> Drools when we redo the ASM based compiler as an extension to MVEL. At 
> this point we'll also look at allowing the bytecode to just be stored 
> externally, such as in a zip. That would provide what you need, but we 
> just aren't there yet. So for now maybe stick with descr analysis, 
> which will work regardless of java or mvel dialec etc.

Something that could be independant of the dialect would be really useful.

>>
>>
>> So if I want to sum up the discussion at this point we have:
>> * Only reflection trick to access generated bytecode
>> * Analysis tools may be appropriate to have some insights of what 
>> will be generated
>> * Rule Pre-compilation is currently not available
> The current way bytecode is stored we aren't going to expose in a 
> manner you want, it's just exposing way too many internals for things 
> we want to change soon. And users tend to shoult at us if we change 
> things they are using. you can always do a patch that does what you 
> need and worked off that patched version of drools.

I understand that nobody wants someone to shout at him :)
Anyway, what I basically would like is not a direct access to drools 
internals, but to the final bytecode result (generated using a classic 
java compiler, ASM or MVEL).
I need only small changes to the Package API, that will expose (or give 
access to) the generated bytecode like a blackbox, no drools internals 
exposed, just a byte[].

Thanks
--G

>>
>> --G
>>
>>> Mark
>>> On 26/10/2010 08:49, Guillaume Sauthier wrote:
>>>> Thanks for your answer Edson.
>>>>
>>>> The reason I have is that runtime generated stuff usually don't fit 
>>>> well
>>>> in an OSGi model.
>>>>
>>>> When you take a bundle, it has a statically defined set of "imported
>>>> packages". that means that when the bundle has been compiled, a 
>>>> list of
>>>> packages to be wired in at deployment time has been computed. This 
>>>> list
>>>> of packages if inferred from what the .class files (in the bundle)
>>>> requires to be executed (think of them as external dependencies).
>>>>
>>>> Now if we generate some classes at runtime in an OSGi environment, we
>>>> can see that generated classes can have different (or additional)
>>>> requirements in terms of java packages. So usually, with OSGi, that 
>>>> ends
>>>> up by adding a special header called DynamicImport-Package into the
>>>> MANIFEST, with the side effects of breaking modularity :-(
>>>>
>>>> This is what I want to avoid by having access to the generated classes
>>>> at the compilation phase: I can then use this bytecode (IOW giving 
>>>> it to
>>>> Bnd [1]) to complete the Import-Package MANIFEST header with the right
>>>> set of imported java packages.
>>>>
>>>> As a second issue, less important for the moment and more runtime
>>>> oriented this time, I would like to know if/how we can add a new 
>>>> kind of
>>>> Resource.
>>>> Once we have generated the bytecode in the compilation phase, we can
>>>> assume that all the stuff is already here in the bundle. Why can't we
>>>> use it ?
>>>> I've seen the PKG Resource type, but it's some kind of 
>>>> serialization of
>>>> a whole Package, couldn't it be possible to have a new Package type 
>>>> (or
>>>> way to create a Package) that can use the ClassLoader to get access to
>>>> the already present bundle's resources instead of using the byte[] 
>>>> from
>>>> the serialized Package ?
>>>>
>>>> WDYT?
>>>>
>>>> Thanks
>>>> --G
>>>>
>>>> [1]. http://www.aqute.biz/Code/Bnd
>>>>
>>>> Le 25/10/2010 21:26, Edson Tirelli a écrit :
>>>>>       Not exactly sure how helpful would it be to store the generated
>>>>> bytecodes in an osgi bundle. Anyway, there is no API right now to do
>>>>> that, but you can use reflection to achieve the same:
>>>>>
>>>>>            PackageCompilationData data = 
>>>>> pkg.getPackageCompilationData();
>>>>>            Field field = 
>>>>> PackageCompilationData.class.getDeclaredField( "store" );
>>>>>            field.setAccessible( true );
>>>>>            Map<String, byte[]>    store = (Map<String, byte[]>) 
>>>>> field.get( data );
>>>>>
>>>>>       If you can justify the need for such an API, I guess we 
>>>>> could be
>>>>> convinced to add one.
>>>>>
>>>>>       Edson
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> 2010/10/25 Guillaume Sauthier<guillaume.sauthier at ow2.org>:
>>>>>
>>>>>> Hi team
>>>>>>
>>>>>> I've tried the IRC (without much success I admit), maybe here 
>>>>>> someone will
>>>>>> have some thoughts to share :)
>>>>>>
>>>>>> I'm looking for a way to "intercept" the classes being generated 
>>>>>> by the
>>>>>> drools compiler.
>>>>>> I've seen that the classes bytecode is stored deep in
>>>>>> PackageStore/JavaDialectRuntimeData, so deep that I cannot easily 
>>>>>> access it
>>>>>> :)
>>>>>> The objective is to be able to give theses classes to Bnd (I want 
>>>>>> to store
>>>>>> all of that in an OSGi bundle) so that appropriate 
>>>>>> Import-Packages can be
>>>>>> computed. That will avoid to have DynamicImport-Packages all 
>>>>>> around my
>>>>>> bundles :)
>>>>>>
>>>>>> Currently, what I get from the drools compiler is a
>>>>>> Collection<KnowledgePackage>    but I have no API (or didn't find 
>>>>>> any) to
>>>>>> access (or know) the classes generated by the compiler.
>>>>>>
>>>>>> Any ideas ?
>>>>>> Thanks
>>>>>> --Guillaume
>>>>>>
>>>>>> _______________________________________________
>>>>>> rules-dev mailing list
>>>>>> rules-dev at lists.jboss.org
>>>>>> https://lists.jboss.org/mailman/listinfo/rules-dev
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>> _______________________________________________
>>>> rules-dev mailing list
>>>> rules-dev at lists.jboss.org
>>>> https://lists.jboss.org/mailman/listinfo/rules-dev
>>>>
>>>>
>>>
>>> _______________________________________________
>>> rules-dev mailing list
>>> rules-dev at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/rules-dev
>>>
>>>
>>
>> _______________________________________________
>> rules-dev mailing list
>> rules-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-dev
>>      
>
>
> _______________________________________________
> rules-dev mailing list
> rules-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-dev
>    
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/rules-dev/attachments/20101103/69522020/attachment-0001.html 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: guillaume_sauthier.vcf
Type: text/x-vcard
Size: 459 bytes
Desc: not available
Url : http://lists.jboss.org/pipermail/rules-dev/attachments/20101103/69522020/attachment-0001.vcf 


More information about the rules-dev mailing list