Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / Virtual Machine / March 2007

Tip: Looking for answers? Try searching our database.

Adding constructor by bytecode instrumentation

Thread view: 
Moritz Hammer - 20 Mar 2007 11:31 GMT
Hello,

I am trying to use JVMTI to instrument the bytecode of all classes up to
java.lang.Object. I need this so I can have a plain constructor (with some
special signature) that does not do anything besides calling a superclass
constructor that also does nothing (I want to simulate the effect of
the actual constructor later). Right now, that does not sound too
complicated to me: add another <init> method in the constant pool and a
method block later. However, before I start, I wanted to ask people who
know whether it can really be done: adding another constructor to
java.lang.Object (or, at least, any direct subclass). Any pitfalls I am
currently heading to? Is there any framework I can use (I do not want
to permanently instrument all Java classes, so unless I am mistaken, I
need to do it with JVMTI and implement it in C to get a grasp on
java.lang.Object).

Any hints are greatly appreciated,
 Moritz
Chris Uppal - 20 Mar 2007 23:59 GMT
> However, before I start, I wanted to ask people who
> know whether it can really be done: adding another constructor to
> java.lang.Object (or, at least, any direct subclass).

Yes it can be done.  I've just tried it with JDK 1.6.0 and it seems to work
fine.

   -- chris
Moritz Hammer - 23 Mar 2007 11:18 GMT
> Yes it can be done.  I've just tried it with JDK 1.6.0 and it seems to work
> fine.
Just for the record: Indeed it works, and it only takes some minor
modification to the java_crw_demo sources supplied with JDK 1.6 (persumably
with 1.5 also) to get things working. There is a minor issue with
obtaining a unique constructor signature, which I first attempted to get
with a unique class reference; but this leads to problems, since the class
loader cannot load the class it has been instrumented with... I would have
to add that class to the bootstrap class loader, but then I just went with
a very obscure combination of primitive types as the signature; it will be
fun to see when I get clashes with existing constructors ;-)

Thank you for your reply,
 Moritz
Chris Uppal - 26 Mar 2007 11:36 GMT
> There is a minor issue with
> obtaining a unique constructor signature, which I first attempted to get
> with a unique class reference; but this leads to problems, since the class
> loader cannot load the class it has been instrumented with...

I used [D[D[D as the signature in my test.  Now I come to think about it, I
can't see why the double[] array doesn't suffer from the same problem (double[]
is a subclass of Object after all).  But, since it doesn't (at least with a Sun
1.6 JVM), a neat way of getting a unique signature is to use something like
   not.defined.Anywhere[]
as the parameter type (pass a null if you want to invoke it, of course).

   -- chris
Moritz Hammer - 26 Mar 2007 13:24 GMT
> I used [D[D[D as the signature in my test.  Now I come to think about
> it, I can't see why the double[] array doesn't suffer from the same
[quoted text clipped - 3 lines]
>     not.defined.Anywhere[]
> as the parameter type (pass a null if you want to invoke it, of course).
Well, I am not entirely sure, but I think it is a bootstrap class loading
issue. java.lang.Object gets loaded anyway, but not.defined.Anywhere
requires a genuine ClassLoader to be loaded, unless put into the bootstrap
classpath. I just checked, if you put it in the bootstrap classpath,
things are working ok. Maybe a cleaner solution than using an "unlikely"
signature - I used "DIFFZIFF" ;-) If not.defined.Anywhere is not put into
the bootstrap classpath, the instrumented ClassLoader subclass gets
screwed, since it requires a loaded instance of not.defined.Anywhere to
get started, and this leads to very strange errors.

Regards,
 Moritz
Chris Uppal - 27 Mar 2007 06:30 GMT
> Maybe a cleaner solution than using an "unlikely"
> signature - I used "DIFFZIFF" ;-) If not.defined.Anywhere is not put into
> the bootstrap classpath, the instrumented ClassLoader subclass gets
> screwed, since it requires a loaded instance of not.defined.Anywhere to
> get started, and this leads to very strange errors.

I'm probably misunderstanding you, but I don't see why you'd have to load class
not.defined.Anywhere at all -- there's no need to create an instance just to
call a method with that signature.  I was able to call my additional Object
constuctor with bytecode:

   new java/lang/Object
   aconst_null
   invokespecial java/lang/Object/<init> ([Lnot/defined/Anywhere;)V

Which worked, in that my constuctor was called, but of course I had nothing
comparable to your custom classloader in my test settup.

   -- chris
Moritz Hammer - 27 Mar 2007 09:58 GMT
> I'm probably misunderstanding you, but I don't see why you'd have to load class
> not.defined.Anywhere at all -- there's no need to create an instance just to
[quoted text clipped - 7 lines]
> Which worked, in that my constuctor was called, but of course I had nothing
> comparable to your custom classloader in my test settup.
I instrument every class with the additional constructor, and if
not.defined.Anywhere is not in the bootclasspath, I get the exception:

Error occurred during initialization of VM
java.lang.NullPointerException
    at java.util.Hashtable.put(Hashtable.java:394)
    at java.lang.System.initProperties(Native Method)
    at java.lang.System.initializeSystemClass(System.java:1072)

This is independent on whether not.defined.Anywhere is in the classpath or
not. I excluded various classes from instrumentation, and eventually found
that if I exclude the ClassLoader subclasses and some classes from sun.*
packages (apparently related to reading the actual bytecode), thinks work
ok. Therefore I suspect that the ClassLoader cannot be instrumented.

If I instrument java.lang.Object only, things are ok even if
not.defined.Anywhere is indeed not defined anywhere. But then I get a
ClassNotFoundException when I use reflection to see the constructors. I
have not tried assembling the bytecode to invoke the special
java.lang.Object constructor. That might work.

I assume you are right, and not.defined.Anywhere needs not be loaded if it
is used for the signature of a constructor invoked directly. If reflection
is used to get the constructor, and I guess this is the case with the
ClassLoader subclasses, then not.defined.Anywhere needs to be loaded.

Regards,
 Moritz
Cyril Shelest - 29 Mar 2007 21:23 GMT
Hi,
I did the same you mentioned. In my product that written with pure C++ I
developed a code that parses Java bytecode, decomposes it into a syntax
tree. The syntax tree is modified to add new methods/constructors. And then
from this syntax tree I generate a new Java bytecode.  The products that
include this algorithm are avalable at
http://www.simtel.net/product.php[id]94368[SiteID]simtel.net
and
http://www.simtel.net/product.php[id]93174[SiteID]simtel.net

> Hello,
>
[quoted text clipped - 14 lines]
> Any hints are greatly appreciated,
>  Moritz


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.