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

Slides:



Advertisements
Similar presentations
1 Dynamic Proxies Explained Simply. 2 Dynamic Proxies License Copyright © 2008 Ciaran McHale. Permission is hereby granted, free of charge, to any person.
Advertisements

Using Java™ Technology Reflection to Improve Design
Chapter 16 Java Virtual Machine. To compile a java program in Simple.java, enter javac Simple.java javac outputs Simple.class, a file that contains bytecode.
Identity and Equality Based on material by Michael Ernst, University of Washington.
Compilation 2007 Code Generation Michael I. Schwartzbach BRICS, University of Aarhus.
Written by: Dr. JJ Shepherd
1 InTroToJCL Introduction to Java Class Loaders. 2 class loader l ia an object responsible for loading classes. The class ClassLoader is an abstract class.
Java Virtual Machine (JVM). Lecture Objectives Learn about the Java Virtual Machine (JVM) Understand the functionalities of the class loader subsystem.
10/18/08 Matt Swatzell. What is Reflection?  Some Definitions….  Reflection is the process by which a program can modify its own behavior.  A program.
Copyright © 2001 Qusay H. Mahmoud Case Study A Global Compute Engine Here we will discuss some implementation details: – Class Loaders – Compute Engine.
15-May-15 RMI Remote Method Invocation. 2 “The network is the computer” Consider the following program organization: If the network is the computer, we.
JVM-1 Java Virtual Machine Reading Assignment: Chapter 1: All Chapter 3: Sections.
Road Map Introduction to object oriented programming. Classes
Remote Method Invocation Chin-Chih Chang. Java Remote Object Invocation In Java, the object is serialized before being passed as a parameter to an RMI.
Dynamic Proxies Amit Shabtay. March 3rd, 2004 Object Oriented Design Course 2 Dynamic Proxies Main idea: The proxy wraps objects and adds functionality.
JVM-1 Java Virtual Machine Reading Assignment: Chapter 1: All Chapter 3: Sections.
Java Virtual Machine (JVM). Lecture Objectives Learn about the Java Virtual Machine (JVM) Understand the functionalities of the class loader subsystem.
© 2006 Pearson Addison-Wesley. All rights reserved4-1 Chapter 4 Data Abstraction: The Walls.
1 Java Reflection. 2 Java looking at Java l One of the unusual capabilities of Java is that a program can examine itself »You can determine the class.
Unit 061 Java Virtual Machine (JVM) What is Java Virtual Machine? The Class Loader Subsystem Linking oVerification oPreparation oResolution Class Initialization.
13-Jul-15 Reflection. 2 Java looking at Java One of the unusual capabilities of Java is that a program can examine itself You can determine the class.
1 Java Server Pages Can web pages be created specially for each user? What part does Java play?
COMP 14: Intro. to Intro. to Programming May 23, 2000 Nick Vallidis.
Java Software Solutions Lewis and Loftus Chapter 2 1 Copyright 1997 by John Lewis and William Loftus. All rights reserved. Software Concepts -- Introduction.
Advance Computer Programming Java Database Connectivity (JDBC) – In order to connect a Java application to a database, you need to use a JDBC driver. –
Programming Languages and Paradigms Object-Oriented Programming.
“is a”  Define a new class DerivedClass which extends BaseClass class BaseClass { // class contents } class DerivedClass : BaseClass { // class.
CISC6795: Spring Object-Oriented Programming: Polymorphism.
EJB Framework.  As we know, EJB is the center of the J2EE architecture that provides a sturdy framework for building enterprise applications. The major.
J2EE Structure & Definitions Catie Welsh CSE 432
Java Reflection. Compile-Time vs Run-Time Some data you know at compile time: int area = radius*radius*3.14; The “3.14” is set – known at compile time.
1 Java Inheritance. 2 Inheritance On the surface, inheritance is a code re-use issue. –we can extend code that is already written in a manageable manner.
Object Oriented Programming in Java Lecture 13. Java Reflection Reflection is a feature unique to Java that allows an executing program to examine or.
Polymorphism, Inheritance Pt. 1 COMP 401, Fall 2014 Lecture 7 9/9/2014.
CS 390- Unix Programming Environment CS 390 Unix Programming Environment Topics to be covered: Distributed Computing Fundamentals.
11 Web Services. 22 Objectives You will be able to Say what a web service is. Write and deploy a simple web service. Test a simple web service. Write.
Netprog: Java Intro1 Crash Course in Java. Netprog: Java Intro2 Why Java? Network Programming in Java is very different than in C/C++ –much more language.
E FFECTIVE C# 50 Specific Ways to Improve Your C# Second Edition Bill Wagner محمد حسین سلطانی.
Spring/2002 Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads 1 RMI.
Enterprise JavaBeans Understanding EJB Components Version 0.1 Kamal Wickramanayake
RMI Remote Method Invocation Distributed Object-based System and RPC Together 2-Jun-16.
 Remote Method Invocation  A true distributed computing application interface for Java, written to provide easy access to objects existing on remote.
Java Dynamic Proxy Bibliography: reflection/proxy.html
© Keren Kalif Advanced Java Topics Written by Keren Kalif, Edited by Liron Blecher.
Creating competitive advantage Copyright © 2003 Enterprise Java Beans Presenter: Wickramanayake HMKSK Version:0.1 Last Updated:
JDBC. Java.sql.package The java.sql package contains various interfaces and classes used by the JDBC API. This collection of interfaces and classes enable.
© FPT SOFTWARE – TRAINING MATERIAL – Internal use 04e-BM/NS/HDCV/FSOFT v2/3 JSP Application Models.
Chapter 8 Class Inheritance and Interfaces F Superclasses and Subclasses  Keywords: super F Overriding methods  The Object Class  Modifiers: protected,
 In the java programming language, a keyword is one of 50 reserved words which have a predefined meaning in the language; because of this,
Access Databases from Java Programs via JDBC Tessema M. Mengistu Department of Computer Science Southern Illinois University Carbondale
CSCE 314 Programming Languages Reflection Dr. Hyunyoung Lee 1.
Chapter 11: Advanced Inheritance Concepts. Objectives Create and use abstract classes Use dynamic method binding Create arrays of subclass objects Use.
Quick Review of OOP Constructs Classes:  Data types for structured data and behavior  fields and methods Objects:  Variables whose data type is a class.
(1) Dynamic Proxies in Java And so on into winter Till even I have ceased To come as a foot printer, And only some slight beast So mousy or foxy Shall.
1 C# - Inheritance and Polymorphism. 2 1.Inheritance 2.Implementing Inheritance in C# 3.Constructor calls in Inheritance 4.Protected Access Modifier 5.The.
Terms and Rules II Professor Evan Korth New York University (All rights reserved)
Author: DoanNX Time: 45’.  OOP concepts  OOP in Java.
CS 440 Database Management Systems Stored procedures & OR mapping 1.
RealTimeSystems Lab Jong-Koo, Lim
Modern Programming Tools And Techniques-I
Chapter 7: Cloning and RTTI
Remote Method Invocation
Presentation on Object Oriented programming Topic
EE 422C Java Reflection re·flec·tion rəˈflekSH(ə)n/ noun
null, true, and false are also reserved.
Java Programming Language
Some Examples Reflection is used for many things:
Java Remote Method Invocation
CSCE 314: Programming Languages Dr. Dylan Shell
Plug-In Architecture Pattern
Presentation transcript:

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

Philly JUG: May 21, 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

Philly JUG: May 21, 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

Philly JUG: May 21, 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

Philly JUG: May 21, Today's Problem Beginning Java code generation, compilation, and loading is slow and resource- intensive. However attempting to avoid it can be even worse!

Philly JUG: May 21, 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

Philly JUG: May 21, 2002 Reflection Review

Philly JUG: May 21, Middle ● 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(...);... }

Philly JUG: May 21, Middle ● 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();... }

Philly JUG: May 21, Middle ● 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();... }

Philly JUG: May 21, Middle ● 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);... }

Philly JUG: May 21, 2002 Dynamic Proxies

Philly JUG: May 21, Middle ● 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

Philly JUG: May 21, Middle Dynamic Proxy Diagram Client Proxy (impl. interfaces) Invocation Handler

Philly JUG: May 21, Middle ● 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

Philly JUG: May 21, Middle InvocationHandler API public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }

Philly JUG: May 21, Middle ● 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

Philly JUG: May 21, Middle 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); }

Philly JUG: May 21, Middle ● 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

Philly JUG: May 21, Middle 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

Philly JUG: May 21, Middle 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)); }

Philly JUG: May 21, Middle Connection Proxy Diagram Client Proxy (impl. Connection) Invocation Handler Real Connection

Philly JUG: May 21, Middle 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!

Philly JUG: May 21, Middle 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; }

Philly JUG: May 21, Middle 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; }

Philly JUG: May 21, Middle 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)...

Philly JUG: May 21, Middle 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])

Philly JUG: May 21, Middle 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 Client Remote Interface Container Bean Instance What implements this?

Philly JUG: May 21, Middle 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.

Philly JUG: May 21, Middle Generated Code Diagram Client Generated Remote Bean Stub Remote Bean Impl Container

Philly JUG: May 21, Middle 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

Philly JUG: May 21, Middle JBoss Proxy Diagram Client Proxy (impl EJB Remote Interface) Invocation Handler Container Remote Stub Container Impl

Philly JUG: May 21, Middle 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

Philly JUG: May 21, Middle 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

Philly JUG: May 21, 2002 Dynamic Classes

Philly JUG: May 21, Middle 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

Philly JUG: May 21, Middle Typical Bytecode public static final int fac(int n) { return (n == 0)? 1 : n * fac(n - 1); } 0: iload_0 1: ifne #8 4: iconst_1 5: goto #16 8: iload_0 9: iload_0 10: iconst_1 11: isub 12: invokestatic SomeClass.fac (I)I (12) 15: imul 16: ireturn

Philly JUG: May 21, Middle 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 ➔ ➔

Philly JUG: May 21, Middle 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

Philly JUG: May 21, Middle 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

Philly JUG: May 21, Middle Solution 1: Write Code, Run Compiler, Load Class... ● This should be familiar by now

Philly JUG: May 21, Middle 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

Philly JUG: May 21, Middle 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)

Philly JUG: May 21, Middle 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

Philly JUG: May 21, Middle 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 ; 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) {...

Philly JUG: May 21, Middle 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("..."); }

Philly JUG: May 21, Middle 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

Philly JUG: May 21, Middle 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(), " ", Constants.ACC_PUBLIC | Constants.ACC_FINAL, new String[0]); pool = clsGen.getConstantPool(); il = new InstructionList(); fields = new HashMap();

Philly JUG: May 21, Middle 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); }

Philly JUG: May 21, Middle 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

Philly JUG: May 21, Middle BCEL: Adding a Method ClassGen clsGen =...; InstructionList il =...; private void createConstructor() { MethodGen mg = new MethodGen( Constants.ACC_PUBLIC, Type.VOID, new Type[]{...}, new String[]{...}, " ", subclassName, il, pool); il.append(new ALOAD(0)); il.append(new PUTFIELD(...)); clsGen.addMethod(mg.getMethod()); il.dispose(); // InstructionList is reusable }

Philly JUG: May 21, Middle 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

Philly JUG: May 21, Middle 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); }

Philly JUG: May 21, Middle 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

Philly JUG: May 21, 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

Philly JUG: May 21, One For The Road End Would it make sense to implement a JSP container using Dynamic Classes?

Philly JUG: May 21, 2002

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