+ All Categories
Home > Documents > Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes...

Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes...

Date post: 29-Jan-2016
Category:
Upload: clement-blair
View: 217 times
Download: 0 times
Share this document with a friend
58
Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code
Transcript
Page 1: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 2002

Dynamic Java

Aaron MulderChief Technical OfficerChariot Solutions

Classes Without Code

Page 2: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021

Learning Objectives

● In this presentation, we'll discuss

➔ Dynamic Proxies

➔ Dynamic Classes, or generating Java classes

without source code

➔ Where these techniques can be useful

Beginning

Page 3: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021

About Aaron Mulder

● Chief Technical Officer at Chariot Solutions

● Co-author of Professional EJB (Wrox Press, 2001)

● Presented at JavaOne 2001 & JavaOne 2002

● A member of the JSR-88 Expert Group (J2EE Deployment API)

● Contributed to the JBoss and OpenEJB projects, including an implementation of Dynamic Proxies for JDK 1.2

Beginning

Page 4: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021

About Chariot Solutions

● Chariot Solutions is an IT service provider, specializing in J2EE

● Chariot project teams include experienced project managers, business analysts, technical architects, and developers

● Chariot's extensive Java tools and application framework can give any Java project a head start

● Flyers around the room have more information

Beginning

Page 5: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021

Today's Problem

Beginning

Java code generation, compilation, and loading is slow and resource-intensive. However attempting to avoid it can be even worse!

Page 6: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021

Presentation Agenda

● Reflection Review

● Dynamic Proxies

● Project 1: Tracing JDBC Driver

● Project 2: EJB 1.1 Client Stubs

● Dynamic Classes

● Project 3: EJB 2.0 CMP

● Wrapup/Q&A

Beginning

Page 7: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 2002

Reflection Review

Page 8: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

● java.lang.Class provides information on the constructors, methods, fields, interfaces implemented, superclass, package, etc. for a class

Reflection Review: Class

public class Class { Field[] getFields(); Field getField(String name); Method[] getMethods(); Method getMethod(String name, Class[] params); Constructor[] getConstructors(); ... getDeclaredXXX(...); ...}

Page 9: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

● java.lang.reflect.Method provides information on the parameters, return type, access modifiers, exceptions, etc. for a method

● java.lang.reflect.Constructor is very similar

Reflection Review: Method & Constructor

public class Method { String getName(); Class getReturnType(); Class[] getParameterTypes(); Class[] getExceptionTypes(); int getModifiers(); ...}

Page 10: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

● java.lang.reflect.Field provides information on the name, type, access modifiers, etc. for a field

Reflection Review: Field

public class Field { String getName(); Class getType(); int getModifiers(); ...}

Page 11: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

● java.lang.reflect.Modifier decodes the Modifiers property (an int) on methods, fields, etc.

Reflection Review: Modifier

public class Modifier { boolean isPublic(int modifiers); boolean isPrivate(int modifiers); boolean isAbstract(int modifiers); boolean isStatic(int modifiers); boolean isFinal(int modifiers); ...}

Page 12: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 2002

Dynamic Proxies

Page 13: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

● Introduced in JDK 1.3➔ java.lang.reflect.Proxy➔ java.lang.reflect.InvocationHandler

● Allow you to implement arbitrary interfaces at runtime

● All calls to Proxy methods are dispatched to an InvocationHandler for processing

● Proxies rely heavily on Reflection

Dynamic Proxies

Page 14: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Dynamic Proxy Diagram

ClientProxy (impl.interfaces)

InvocationHandler

Page 15: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

● java.lang.reflect.InvocationHandler has one method, which takes as arguments:

➔ The proxy that was called➔ The Method object representing the method

which was called➔ The objects which were passed as parameters

to the method

● It returns an Object; the value to return from the method call, or null for void methods

● It throws Throwable

InvocationHandler

Page 16: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

InvocationHandler API

public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;}

Page 17: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

● java.lang.reflect.Proxy has methods which:➔ Create a new proxy class (based on the

combination of interfaces)➔ Create a new proxy instance (uses a proxy class

created above, for a specific InvocationHandler)➔ Get the InvocationHandler for a proxy➔ Check whether an arbitrary object is a proxy

Proxy

Page 18: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Proxy API

public class Proxy {

public Class getProxyClass(ClassLoader loader, Class[] interfaces);

public Object newProxyInstance( ClassLoader loader, Class[] interfaces, InvocationHandler handler);

public InvocationHandler getInvocationHandler( Object proxy);

public boolean isProxyClass(Class class);}

Page 19: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

● What if you want a log of all SQL statements executed?

● But you don't want to add code everywhere you issue a JDBC command (or the app server is doing all the JDBC for you)

● And you want to be able to turn it on or off via config files

● And you want to see all the values in place in every PreparedStatement

Project 1: Tracing JDBC Driver

Page 20: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Why Dynamic Proxies Fit

● The JDBC API is made up entirely of interfaces

● Which driver is used is (typically) controlled by config files

● One driver can wrap another

● Implementing all the interfaces is a ton of code (100s of methods), when we only want to act on a couple of them (executeQuery), and pass the rest directly to the wrapped instance

Page 21: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

JDBC Driver Class

public boolean acceptsURL(String url) { return url.startsWith("jdbc:trace:");}

public Connection connect(String url, Properties info) { String driver = info.getProperty("driver"); if(driver != null && !loaded.contains(driver)) // Load the driver String realUrl = "jdbc:"+url.substring(11); Connection con = DriverManager.getConnection( realUrl, info); return (Connection)Proxy.newProxyInstance( getClass().getClassLoader(), new Class[]{java.sql.Connection.class}, new ConnectionHandler(con));}

Page 22: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Connection Proxy Diagram

ClientProxy (impl.Connection)

InvocationHandler

RealConnection

Page 23: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

ConnectionHandler Class

private Connection con;...public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(method.getName().equals("isClosed")) { return con == null; } if(con == null) { throw new SQLException("Con. closed!"); } Method conMeth = con.getClass().getMethod( method.getName(), method.getParameterTypes()); Object result = conMeth.invoke(con, args); if(method.getName().equals("close")) { con = null; } ... // To Be Continued!

Page 24: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

ConnectionHandler, continued

if(method.getName().equals("createStatement")){ return (Statement)Proxy.newProxyInstance( getClass().getClassLoader(), new Class[]{java.sql.Statement.class}, new StatementHandler((Statement)result)); } if(method.getName().equals("prepareStatement")){ return (PreparedStatement) Proxy.newProxyInstance( getClass().getClassLoader(), new Class[]{java.sql.PreparedStatement.class}, new PreparedStatementHandler( (PreparedStatement)result, (String)args[0]) // this is the SQL ); } return result;}

Page 25: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

StatementHandler

private Statement st;...public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(method.getName().equals("executeQuery") || method.getName().equals("executeUpdate")) { log(args[0]); // args[0] is the SQL! } Method meth = st.getClass().getMethod( method.getName(), method.getParameterTypes()); Object result = meth.invoke(st, args); if(method.getName().equals("close")) { st = null; } return result;}

Page 26: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

PreparedStatementHandler

private PreparedStatement st;private String sql;private Map values = new HashMap();...public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(method.getName().startsWith("set")) { values.put(args[0], args[1]); // args[0] = index, args[1] = value } if(method.getName().startsWith("execute")) { log(writeValues(sql, values)); values.clear(); } // execute the method on the underlying PS // return the result}private static String writeValues(String, Map)...

Page 27: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Sample JDBC Driver Output

● JDBC URL = jdbc:driver:...➔ no output

● JDBC URL = jdbc:trace:driver:...

SELECT WL0.check_date, WL0.company_no, WL0.create_datetime, WL0.create_username, WL0.cutoff_date, WL0.due_date_flag, WL0.payables_selected, WL0.update_datetime, WL0.update_username FROM dbo.ap_selection WL0 WHERE (WL0.company_no = [6])

Page 28: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Project 2: EJB Client Stubs

● EJB Architecture➔ Client deals with remote interface➔ Container must implement remote interface,

handle RMI and translate calls to run against a bean instance

➔ Bean instance isn't remote and doesn't implement remote interface, so container must create some "glue" code

ClientRemoteInterface

ContainerBeanInstance

What implements this?

Page 29: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Solution 1: "That Other App Server"

● At deployment time, container generates a class which is remote, implements the remote interface, and dispatches calls back to the container

● Java source code is written to disk

● Java compiler is run (in another process)

● Source code is deleted

● Class files are loaded from disk

● Deploying lots of beans takes... a long time.

Page 30: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Generated Code Diagram

ClientGeneratedRemote BeanStub

RemoteBean Impl

Container

Page 31: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Solution 2: JBoss Dynamic Proxies

● A Proxy is generated for each bean to implement the EJB's Remote Interface

● One prewritten InvocationHandler class is used for all beans of a given type (Entity, Stateless Session, etc.)

● The InvocationHandler has a reference to the Container (as a remote object)

● The InvocationHandler parameterizes the Method and sends it with the arguments to the Container for processing

Page 32: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

JBoss Proxy Diagram

Client Proxy (implEJB RemoteInterface)

InvocationHandler

ContainerRemote Stub

ContainerImpl

Page 33: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Sample InvocationHandler Code

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(proxy instanceof EJBHome) { return Container.executeHome(proxy, encode(method), args); } else { return Container.executeRemote(proxy, encode(method), args); }

● Real code lives in org.jboss.ejb.plugin.jrmp for JBoss 2.x (but the classes named "Proxy" are really the InvocationHandlers)

● Method objects regrettably aren't Serializable

Page 34: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Dynamic Proxy Review

● Dynamic Proxies can be used to implement arbitrary interfaces at runtime

● The client casts the Proxy to an instance of one of the implemented interfaces

● An InvocationHandler handles all calls to the Proxy

● Dynamic Proxies can't be used to extend existing classes

Page 35: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 2002

Dynamic Classes

Page 36: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Dynamic Classes

● The hardcore solution

● Involves assembling bytecode into classes

● Requires an understanding of bytecode instructions (essentially, assembly language for the Java Virtual Machine)

● However, existing bytecode libraries can help manage the worst parts of it

Page 37: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Typical Bytecode

public static final int fac(int n) { return (n == 0)? 1 : n * fac(n - 1);}

0: iload_01: ifne #84: iconst_15: goto #168: iload_09: iload_010: iconst_111: isub12: invokestatic SomeClass.fac (I)I (12)15: imul16: ireturn

Page 38: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Alternatives to Dynamic Classes

● Write Java code, run a compiler, delete the code, load the class, blah, blah, blah...

● Interpret some other minimal "language" – regular expressions, for example

● The alternatives are usually somewhat clearer (i.e. not bytecode), but bigger and slower

● If you do proceed... use a library➔ BCEL @ http://jakarta.apache.org/bcel/➔ gnu.bytecode @

http://sources.redhat.com/kawa/api/gnu/bytecode/

Page 39: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

BCEL (Byte Code Engineering Library)

● Includes numerous helper classes➔ ClassGen, for creating a class➔ MethodGen, for creating a method➔ FieldGen, for creating a field➔ ConstantPoolGen, for managing the Constant

Pool (a necessary feature of Java classes)➔ InstructionList, for assembling instructions➔ Constant, a list of helpful constants

Page 40: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Project 3: EJB 2.0 CMP

● EJB 2.0 CMP entity bean instances are abstract classes

public abstract class UserBean implements EntityBean { public abstract int getUserID(); public abstract void setUserID(int userID);

public abstract String getUsername(); public abstract void setUsername(String name);

public abstract String getPassword(); public abstract void setPassword(String pw); ...

● Container must generate a subclass in order to instantiate bean instances

Page 41: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Solution 1: Write Code, Run Compiler, Load Class...

● This should be familiar by now

Page 42: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Solution 2: Extend Dynamic Proxies

● JBoss 3.x uses this approach

● Must re-implement Dynamic Proxies in order to extend their capabilities

● Add the ability to extend an abstract class in addition to implementing interfaces

● Abstract method calls are passed to the InvocationHandler just like calls to interface methods

● JBoss uses BCEL to do this, but it's way too complicated to go into here

Page 43: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Solution 3: Generate a Concrete Subclass

● Generate a dynamic class which extends the abstract bean instance class

● Lets you hardcode more container-specific behavior as compared to extending Dynamic Proxies (i.e. a modified flag)

● The subclass can look pretty much like an EJB 1.x bean (with CMR and other new features, of course)

Page 44: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Dynamic Class Procedure

● Figure out what the generated class should look like

● Write Java code for an example desired class (in this case, create the abstract superclass too)

● Write a test class to test all the features of the output class, using Reflection

● Run "javap -c" on the desired class to see its bytecode

● Write the BCEL code to produce the output class

Page 45: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Desired Java Code

public class UserBeanTemplate extends UserBean { // Custom instance variables private boolean modified = false; // Instance variables for CMP fields public int userID; public String username; public String password; public String fullName; public String email; public Timestamp createDate; // Methods for CMP fields public int getUserID() {return userID;} public void setUserID(int userID) { this.userID = userID; modified = true; } public String getUsername() {return username;} public void setUsername(String username) { ...

Page 46: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Test Class

private Class outputCls;... testConstructor(); testCMPFields(); testCMPMethods();...private void testConstructor() throws BadClassEx { try { Constructor con = outputCls.getConstructor( new Class[]{...}); if(!Modifier.isPublic(con.getModifiers())) { throw new BadClassEx("..."); } } catch (NoSuchMethodException e) { throw new BadClassEx("..."); } catch (SecurityException e) { throw new BadClassEx("..."); }}

Page 47: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

BCEL: Preparing To Create A Class

● In order to generate a class we need:➔ The name of the new class➔ The name of the superclass➔ The name of the source file it came from (we'll

make something up)➔ The modifiers for the class (public, etc.)➔ The names of any interfaces the class

implements

Page 48: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

BCEL: Initializing a class

private Class source;private ClassGen clsGen;private ConstantPoolGen pool;private InstructionList il;private Map fields;private String subclassName;

... subclassName = source.getName()+"Impl"; clsGen = new ClassGen(subclassName, source.getName(), "<generated>", Constants.ACC_PUBLIC | Constants.ACC_FINAL, new String[0]); pool = clsGen.getConstantPool(); il = new InstructionList(); fields = new HashMap();

Page 49: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

BCEL: Adding a Field

● In order to add a field, we need the field modifiers (public, etc.), field type, field name, and a reference to the Constant Pool

ClassGen clsGen = ...;FieldGen fg;for(int i=0; i<properties.length; i++) { fg = new FieldGen(Constants.ACC_PUBLIC, BCELUtilities.getType(properties[i].type), properties[i].name, pool); Field f = fg.getField(); fields.put(properties[i].name, f); clsGen.addField(f);}

Page 50: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

BCEL: Preparing to Add a Method

● In order to add a method, we need:➔ The method modifiers (public, etc.)➔ The return type➔ The parameter types➔ The parameter names➔ The method name➔ The owning class name➔ The code for the method (including Exception

handling)➔ A reference to the Constant Pool

Page 51: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

BCEL: Adding a Method

ClassGen clsGen = ...;InstructionList il = ...;

private void createConstructor() { MethodGen mg = new MethodGen( Constants.ACC_PUBLIC, Type.VOID, new Type[]{...}, new String[]{...}, "<init>", subclassName, il, pool); il.append(new ALOAD(0)); il.append(new PUTFIELD(...)); clsGen.addMethod(mg.getMethod()); il.dispose(); // InstructionList is reusable}

Page 52: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

BCEL: Generating the Bytecode

● Once you've added the fields and methods, it's easy to get the resulting bytecode

ClassGen clsGen = ...;

byte[] code = clsGen.getJavaClass().getBytes();

● However, loading the class is an adventure too

● Default ClassLoaders aren't prepared to load a class from a byte array in memory

Page 53: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Loading A Dynamic Class

public class DynLdr extends ClassLoader { private Class dynClass; private String clsName;

public ProxyLoader(ClassLoader parent, String clsName, byte[] code) { super(parent); this.clsName = clsName; dynClass = defineClass(className, code, 0, code.length); }

protected synchronized Class loadClass( String name, boolean resolve) throws ClassNotFoundException {

if(name.equals(clsName)) {return dynClass;} return getParent().loadClass(name); }}

Page 54: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021Middle

Dynamic Class Review

● It's painful to write in bytecode

● But it's much faster to generate bytecode directly at runtime, compared to generating source code and then running the compiler

● Dynamic classes should only be used when the performance advantage is significant

● Other potential uses include: Serialization, Regular Expressions, extensions to the Java language (Aspects, Generics, etc.), and more

Page 55: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021

Summary

● Dynamic Java is an excellent tool for➔ avoiding generating & compiling Java code➔ avoiding interpreting complex languages➔ avoiding ongoing Reflection at runtime

● Dynamic Proxies can easily implement interfaces at runtime

● Dynamic Classes are more challenging, but can solve more problems as well

● Use these tools wisely; make sure there's a substantive advantage

End

Page 56: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021

One For The Road

End

Would it make sense to implement a JSP container using Dynamic Classes?

Page 57: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 2002

Page 58: Philly JUG: May 21, 2002 Dynamic Java Aaron Mulder Chief Technical Officer Chariot Solutions Classes Without Code.

Philly JUG: May 21, 20021

Slides

● Slides from this presentation and the complete code for all snippets will be available soon at:

http://www.chariotsolutions.com/phillyjug/

End


Recommended