Created a class dynamically but could not use it to create typedobjects

L

lbrtchx

I know I am pushing things a bit but I need to do things this way

I need to create some classes (which will be mostly used as DTO and
DAO) and I used ASM

The thing is that then I cannot do such things as:(this is pseudo
code I have tried many different things to no avail):

Class K = _.getKlass();
K0 Obj = (K0)K.newInstance

ArrayList<K0> ALK0 = new ArrayList<K0>();
ALK0.add(Obj);

Even though I know he name of the class is that I created saved and
loaded in the same context using the URLClassLoader is "K0"

I know the created classes themselves are fine because the JVM (javap
and java) did not complain at all and I actually used the classes by
starting other JVM and reaching out for them

Again I need to use the created classes to create and used typed
objects right within the same context that they were created, without
having to restart java

How could you achieve such a thing, either in a plain way or hacking
my way through?

In case this can not be done (well, this may be why some frameworks
such as JAXB use precompilation of type classes), please let me know
what am I missing here

Thanks
lbrtchx

Here is a short code sample of what I am trying to achieve:
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

import java.util.*;
import java.io.*;
import java.net.*;
import java.security.*;

import org.objectweb.asm.*;
import static org.objectweb.asm.Opcodes.*;

// __
class ASMKW02 extends ClassLoader{
private File FlDir;
private String aKName;
private String[][] aFldDefs;

// __ more sanity checks
ASMKW02(File FlDir, String aKName, String[][] aFldDefs){
if(!FlDir.exists()){ FlDir.mkdirs(); }
this.FlDir = FlDir;
this.aKName = aKName;
this.aFldDefs = aFldDefs;
}
// __
public Class getK(){
Class K = null;

// __
ClassWriter KW = new ClassWriter(ClassWriter.COMPUTE_MAXS);

// __ class def.
KW.visit(V1_6, ACC_PUBLIC, aKName, null, "java/lang/Object", null);

// __ default constructor
MethodVisitor DfltCtor = KW.visitMethod(ACC_PUBLIC, "<init>", "()V",
null, null);
if(DfltCtor != null) {
DfltCtor.visitCode();
DfltCtor.visitVarInsn(ALOAD, 0);
DfltCtor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object",
"<init>", "()V");
DfltCtor.visitInsn(RETURN);
DfltCtor.visitMaxs(1, 1);
DfltCtor.visitEnd();
}
// __ K Fields
FieldVisitor FV;
for(int i = 0; (i < aFldDefs.length); ++i){
FV = KW.visitField(ACC_PUBLIC, aFldDefs[0], aFldDefs[1],
null, null);
if(FV != null){ FV.visitEnd(); }
else{} // . . .
}
// __
KW.visitEnd();

// __
byte[] bKAr = KW.toByteArray();

// __ Checking if class has been already loaded by JVM . . .
File Fl = new File(FlDir, aKName + ".class");
try{
ClassLoader KLCtxt =
Thread.currentThread().getContextClassLoader();
URL U = (Fl.toURI()).toURL();
URLClassLoader UKL = new URLClassLoader(new URL[]{U}, KLCtxt);

try{ K = Class.forName(aKName, true, UKL); }
catch(ClassNotFoundException KNFX)
{ KNFX.printStackTrace(System.err); }
if(K == null){

// __
K = defineClass(aKName, bKAr, 0, bKAr.length);
if(K != null){
System.out.println("// __ Class K: |" + K + "|");
try{
FileOutputStream FOS = new FileOutputStream(Fl);
FOS.write(bKAr);
FOS.close();
}catch(FileNotFoundException FNFX)
{ FNFX.printStackTrace(System.err); }
catch(IOException IOX){ IOX.printStackTrace(System.err); }
}
}
}catch(MalformedURLException MFX)
{ MFX.printStackTrace(System.err); }
// __
return(K);
}
}

// __
public class ASMKW02Test{
public static void main(String[] aArgs){
// __
String aKLoadDir = "/media/sda2/prjx/java/Ks";
File FlDir = new File(aKLoadDir);
// __ K Name
String aKName = "KNm00";
// __ K Fields
String[][] aFldDefs = new String[][]{
{"bByte", "B"}, // byte
{"cChar", "C"}, // char
{"dDouble", "D"}, // double
{"fFloat", "F"}, // float
{"iInt", "I"}, // int
{"lLong", "J"}, // long
{"sShort", "S"}, // short
{"Is", "Z"}, // boolean
{"aNm", "Ljava/lang/String;"},
{"ALS", "Ljava/util/ArrayList<String>;"},
{"HMSI", "Ljava/util/Hasmap<String, Integer>;"}
};
// __
ASMKW02 ASMK = new ASMKW02(FlDir, aKName, aFldDefs);
Class K = ASMK.getK();
System.out.println("// __ Class K: |" + K + "|");
try{
K.newInstance();
}catch(InstantiationException InstX)
{ InstX.printStackTrace(System.err); }
catch(IllegalAccessException IlglAxX)
{ IlglAxX.printStackTrace(System.err); }
}
}
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 
O

Owen Jacobson

 I know I am pushing things a bit but I need to do things this way

 I need to create some classes (which will be mostly used as DTO and
DAO) and I used ASM

 The thing is that then I cannot do such things as:(this is pseudo
code I have tried many different things to no avail):

 Class K = _.getKlass();
 K0 Obj = (K0)K.newInstance

If I've read you right, the type K0 is created at runtime.
 ArrayList<K0> ALK0 = new ArrayList<K0>();
 ALK0.add(Obj);

Generics are checked at compile time, well before K0 ever exists.

If your generated DAOs implement a known interface that exists at
compile time, then you can cast them to that and create a generic list
whose type parameter is that interface, but you can't use generics
with the actual type of a class created at runtime.

-o
 
L

lbrtchx

If I've read you right, the type K0 is created at runtime.

Yes, it is
Generics are checked at compile time, well before K0 ever exists.

Well, this is what I know ;-), but I wanted to somehow find out about
some magic trick that would let me get the structure to describe some
entity from which I will only know at run time and then operate on it
If your generated DAOs implement a known interface that exists at
compile time, then you can cast them to that and create a generic list
whose type parameter is that interface, but you can't use generics
with the actual type of a class created at runtime.

I will look into using a registry of interfaces then

lbrtchx
 
L

lbrtchx

I have had my second thoughts

how does JASPER recompile a JSP, which is ultimately a sevlet/java
class file, and updates itself when you, say include new classes to be
used by a JSP?

What happens when these classes include generics?

Tomcat's main process doesn't have to be restarted, so something must
be happening there for jasper/the servlet engine to load these new
classes

lbrtchx
 
A

Arne Vajhøj

I have had my second thoughts

how does JASPER recompile a JSP, which is ultimately a sevlet/java
class file, and updates itself when you, say include new classes to be
used by a JSP?

What happens when these classes include generics?

Tomcat's main process doesn't have to be restarted, so something must
be happening there for jasper/the servlet engine to load these new
classes

You can reload a class by using a new classloader (and let the
old classloader and all objects of classes loaded by it go to GC).

Arne
 
L

lbrtchx

You can reload a class by using a new classloader (and let the
old classloader and all objects of classes loaded by it go to GC).
~
OK, I think my seconds thoughts were not baseless, as tomcat showed
to me generics don't appear to depend solely on compile time checks
and/or there definitely is a way around it
~
I think there should be a way to load and handle generic classes at
run time. Tomcat does it
~
This is what I did to see what was going on with tc classloaders and
generic classes:
~
1) in catalina.sh I declared: CATALINA_OPTS=-verbose:class
~
2) in /webapps/ROOT/META-INF/context.xml I set: reloadable="true"
~
3) then I used some test classes to play with tc loaders and see live
how it would indeed reload changed and totally new class, even generic
ones

package test.k00;
public class K00{
public int i0;
public long l0;
}

package test.k00;
public class K02{
public int i2;
public String aS2;
}

package test.k00;
import java.util.*;
// __
public class GenK00<T>{
private String aS;
public ArrayList<T> ALK00 = new ArrayList<T>();
// __
public GenK00(String aS){
this.aS = aS;
}
}

~
4) Inside of index.jsp I included:

<p>
Loading Generic classes:<br/>
<%@page import="test.k00.*"%>

<%
GenK00<String> GK0 = new GenK00<String>("<String>");
GK0.ALK00.add("blue");
GK0.ALK00.add("rote");
GK0.ALK00.add("blanco");

K00 k0 = new K00();
k0.i0 = 0;
k0.l0 = 0L;

K00 k1 = new K00();
k1.i0 = 1;
k1.l0 = 1L;

K00 k2 = new K00();
k2.i0 = 2;
k2.l0 = 2L;

GenK00<K00> GK2 = new GenK00<K00>("K00");
GK2.ALK00.add(k0);
GK2.ALK00.add(k1);
GK2.ALK00.add(k2);
GK2.ALK00.add(k1);

K02 J = new K02();
J.i2 = 4748;
J.aS2 = "aS2";
%>

<br/>
GK0.ALK00.size(): <%=GK0.ALK00.size()%>

<br/>
GK0.ALK00: <%=GK0.ALK00%>

<br/>
GK2.ALK00.size(): <%=GK2.ALK00.size()%>

<br/>
GK2.ALK00: <%=GK2.ALK00%>

<br/>
J: <%=J%>
</p>

So all that I needs to be done is look into tc classloaders

Am I missing anything here?

lbrtchx
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top