notifyAll in VMProcess
Hi all, There's a mismatch between comment and implementation in vm/reference/java/lang/VMProcess.java. The text says: The instance is Object.notifyAll'd each time the state changes. But the implementation actually only calls notify. By looking at the code, it makes sense that the instance should be notifyAll'd because multiple threads may be waiting on a VMProcess (through waitFor or destroy). So is that a bug in the implementation, or am I missing something? Cheers, Nicolas
Re: [cp-patches] FYI: Add VM updates in 0.98
Hi Andrew, Andrew John Hughes wrote: This updates NEWS with the VM updates in 0.98. 2009-02-05 Andrew John Hughes ahug...@redhat.com * NEWS: Add VM updates. So I guess it's too late now, but forgot to talk about VMField, VMMethod and VMConstructor which I think are new in 0.98. Cheers, Nicolas
Integer.parseInt(+42) gives -42
With the following testcase (Test.java attached), the output of jamvm is: -42 It should have thrown an exception. I attached a patch to correct Integer.java. I could commit it, but I can't find my username/password. Can someone commit it? (I already wrote to classpath-patches, but I may have a bigger audience here) Thanks, Nicolas public class Test { public static void main(String[] args) { System.out.println(Integer.parseInt(+42)); } } --- Integer.java 2008-05-03 19:01:55.0 +0200 +++ Integer.java 2008-05-03 19:02:53.0 +0200 @@ -776,13 +776,12 @@ if (len == 0) throw new NumberFormatException(string length is null); int ch = str.charAt(index); -if (ch == '-' || ch == '+') +if (ch == '+') + throw new NumberFormatException(For input string + str); +if (ch == '-') { if (len == 1) - if (ch == '-') -throw new NumberFormatException(pure '-'); - else if (ch == '+') -throw new NumberFormatException(pure '+'); + throw new NumberFormatException(pure '-'); isNeg = true; ch = str.charAt(++index); }
Re: Integer.parseInt(+42) gives -42
Hehe, didn't know I would made so much noise :) Indeed, I do have a copyright assignment. It's just that I can't find my username/passwd for commits. So I guessed it'd be easier to ask you guys. As for the patch, I followed the 1.6 rule, which throws an exception. If it's not the case anymore with 1.7, I'm still glad I made you notice the bug :) Cheers, Nicolas Mark Wielaard wrote: Hi, On Mon, 2008-05-12 at 13:52 -0700, David Daney wrote: Do you have a copyright assignment? If so, I'll test and commit on your behalf. I am not an expert in this realm, but this may be small enough so that an assignment is not necessary. Perhaps someone like MJW could comment. I think the patch is good (lets make sure Mauve has this test added also). Nicolas does have paperwork on file with the FSF for GNU Classpath. And this fix is indeed small enough to be considered legally significant for copyright purposes (although if someone regularly contributes such changes it is still a good idea to make sure we have a paper trail of where the changes came from). So in summary: Lets get this patch in! :) Cheers, Mark
[cp-patches] Integer.parseInt does not throw an exception when str=+42
The following change: 2007-07-03 Tania Bento [EMAIL PROTECTED] mailto:[EMAIL PROTECTED] * java/lang/Integer.java: (parseInt(String,int,boolean)): Throw NumberFormatException if String is just +. Introduced a regression if String is +X where X is any number (mauve test gnu.testlet.java.lang.Integer.parseInt). The following patch changes parseInt to have the correct behavior. Can someone commit it? Thanks, Nicolas
Re: [cp-patches] Integer.parseInt does not throw an exception when str=+42
And here's the patch :) [EMAIL PROTECTED] wrote: The following change: 2007-07-03 Tania Bento [EMAIL PROTECTED] mailto:[EMAIL PROTECTED] * java/lang/Integer.java: (parseInt(String,int,boolean)): Throw NumberFormatException if String is just +. Introduced a regression if String is +X where X is any number (mauve test gnu.testlet.java.lang.Integer.parseInt). The following patch changes parseInt to have the correct behavior. Can someone commit it? Thanks, Nicolas --- Integer.java 2008-05-03 19:01:55.0 +0200 +++ Integer.java 2008-05-03 19:02:53.0 +0200 @@ -776,13 +776,12 @@ if (len == 0) throw new NumberFormatException(string length is null); int ch = str.charAt(index); -if (ch == '-' || ch == '+') +if (ch == '+') + throw new NumberFormatException(For input string + str); +if (ch == '-') { if (len == 1) - if (ch == '-') -throw new NumberFormatException(pure '-'); - else if (ch == '+') -throw new NumberFormatException(pure '+'); + throw new NumberFormatException(pure '-'); isNeg = true; ch = str.charAt(++index); }
Re: [cp-patches] Integer.parseInt does not throw an exception when str=+42
Andrew Haley wrote: [EMAIL PROTECTED] wrote: And here's the patch :) [EMAIL PROTECTED] wrote: The following change: 2007-07-03 Tania Bento [EMAIL PROTECTED] mailto:[EMAIL PROTECTED] * java/lang/Integer.java: (parseInt(String,int,boolean)): Throw NumberFormatException if String is just +. Introduced a regression if String is +X where X is any number (mauve test gnu.testlet.java.lang.Integer.parseInt). The following patch changes parseInt to have the correct behavior. Can someone commit it? But it's wrong. According to the doc, The characters in the string must all be decimal digits, except that the first character may be an ASCII minus sign '-' ('\u002D') to indicate a negative value Yes, but it may not be a '+'. With the current implementation, parseInt(+32) gives -32. It should throw a NumberFormatException (which is what the patch does). Nicolas Andrew.
Re: [cp-patches] RFC: change in VMClassLoader to define boot packages
Hi Oliver, This is fine for me. About the Index.list file, maybe we should force it to be in glibj.zip? Best, Nicolas Olivier Jolly wrote: Hi, in the VMClassLoader reference file, we have a method to define boot packages and tell vm implementors that they may override it. I propose this patch to use the META-INF/INDEX.LIST in the glibj.zip file (if this entry exists) to predefine boot packages as all packages found in this archive. Thanks for the feedback. Regards +Olivier 2006-04-13 Olivier Jolly [EMAIL PROTECTED] * vm/reference/java/lang/VMClassLoader.java (getBootPackages): Loads boot packages list from the META-INF/INDEX.LIST file if it exists. Index: VMClassLoader.java === RCS file: /sources/classpath/classpath/vm/reference/java/lang/VMClassLoader.java,v retrieving revision 1.34 diff -u -r1.34 VMClassLoader.java --- VMClassLoader.java 2 Mar 2006 00:36:44 - 1.34 +++ VMClassLoader.java 13 Apr 2006 19:32:24 - @@ -1,6 +1,6 @@ /* VMClassLoader.java -- Reference implementation of native interface required by ClassLoader - Copyright (C) 1998, 2001, 2002, 2004, 2005 Free Software Foundation + Copyright (C) 1998, 2001, 2002, 2004, 2005, 2006 Free Software Foundation This file is part of GNU Classpath. @@ -39,17 +39,21 @@ package java.lang; -import gnu.classpath.SystemProperties; import gnu.classpath.Configuration; +import gnu.classpath.SystemProperties; +import java.io.BufferedReader; import java.io.File; import java.io.IOException; +import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; import java.security.ProtectionDomain; import java.util.Enumeration; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.StringTokenizer; import java.util.Vector; import java.util.zip.ZipFile; @@ -235,12 +239,46 @@ /** * Returns a String[] of native package names. The default - * implementation returns an empty array, or you may decide - * this needs native help. + * implementation tries to load a list of package from + * the META-INF/INDEX.LIST file in the boot jar file. + * If not found or if any exception is raised, it returns + * an empty array. You may decide this needs native help. */ private static String[] getBootPackages() { -return new String[0]; +URL indexList = getResource(META-INF/INDEX.LIST); +if (indexList != null) + { +try + { +Set packageSet = new HashSet(); +String line; +int lineToSkip = 3; +BufferedReader reader = new BufferedReader( + new InputStreamReader( + indexList.openStream())); +while ((line = reader.readLine()) != null) + { +if (lineToSkip == 0) + { +if (line.length() == 0) + lineToSkip = 1; +else + packageSet.add(line.replace('/', '.')); + } +else + lineToSkip--; + } +reader.close(); +return (String[]) packageSet.toArray(new String[packageSet.size()]); + } +catch (IOException e) + { +return new String[0]; + } + } +else + return new String[0]; }
Re: RFC: VMClassLoader changes proposition
Hi Olivier, Olivier Jolly wrote: Hi, it seems to me that there is a missing/incomplete feature in the VMClassLoader. For now, the vm implementation are not encouraged, helped nor told to define packages in which classes are loaded from when the boot class loader is defining them. Notably, this makes such that java.lang package is not defined (i.e. basically getPackage on the VMClassLoader for java.lang is null) Well the actual comment on the getBootPackages method are /** * Returns a String[] of native package names. The default * implementation returns an empty array, or you may decide * this needs native help. */ So if the VM implementer decides that he wants to return the strings of all gnu-classpath + vm-specific packages, he has to redefine getBootPackages. We could force getBootPackages to be native though. I spent my week end trying to hack cacao to call a new VMClassLoader method (definePackageIfNeeded) in the native implementation of VMClassLoader.loadClass. I had to skip this call when the loaded class was coming from java.lang.** since the definePackageIfNeeded was using java.lang.** classes and we would run into an infinite loop else. The definePackageIfNeeded is taking a class name as parameter and extract the package name and then defines the package using default values for vendor and such (like the reference clinit of VMClassLoader) if it's not defined yet. Since java.lang.** packages can not be defined by this method, I overrided the getBootPackages reference method to return the java.lang.** packages (which are then defined by the clinit) Please find attached the hack I did on my environment (which I do not consider to be usable but a working proof of concept) as a support of my explanations. This looks complex compared to the (native - should be) getBootPackages method. Maybe I'm missing something, but all of this can be solved by implementing the getBootPackages on the VM side. Best, Nicolas
Re: [cp-patches] FYI: RMI/java.io bug 25520 fix in VMObjectInputStream
Hi Audrius Audrius Meskauskas wrote: Hi, Nicolas, Are you sure this is the correct behaviour? The class of the stream (which contains the members that couldn't be unserialized and were the cause of the bug) is loaded in RMI with the resolveClass method of the gnu.java.rmi.server.RMIObjectInputStream. This method calls the java.rmi.server.RMIClassLoader.loadClass() which uses a specific class loader. Shouldn't the fields be loaded by this class loader instead of the application's class loader (which is actually the thread's context class loader)? The thread context class loader need not be always the applications class loader, this is just the default value. To load remote classes in the ObjectInputStream methods, the mentioned RMI-specific class loader should probably be set as the thread context class loader. That was my conclusion :). In fact I was asking for your opinion. (and any RMI expert on the list) This must be done before that thread calls methods of the ObjectInputStream. This another future fix would be additional to the recently applied patch, actualy solving another bug (remote class loading problems). Yes, it would be additional. I'm no expert on RMI and was asking if you thought my conlusion was right. Maybe it's no sense to change the thread's class loader to correct this issue, or maybe this is the correct behaviour. Regards Audrius Cheers, Nicolas
[cp-patches] FYI : updated documentation of Instrumentation
Hi, This should have been done a long time ago. I updated the documentation of the instrumentation code in file vmintegration.texinfo to reflect the new implementation (see http://lists.gnu.org/archive/html/classpath-patches/2005-12/msg00111.html) Nicolas 2006-01-16 Nicolas Geoffray [EMAIL PROTECTED] * doc/vmintegration.texinfo: Updated subsection of the java.lang.InstrumentationImpl documentation. Index: doc/vmintegration.texinfo === RCS file: /cvsroot/classpath/classpath/doc/vmintegration.texinfo,v retrieving revision 1.20 diff -r1.20 vmintegration.texinfo 691c691 @code{java.lang.InstrumentationImpl} provides an implementation of the --- @code{java.lang.InstrumentationImpl} classes provide an implementation of the 694,697c694,698 A @code{InstrumentationImpl} object should be given to any agent given in the command line (see the @code{java.lang.instrument} package documentation). A VM has to implement the static native methods of the @code{VMInstrumentationImpl} class. --- A @code{InstrumentationImpl} object should be created by the VM when agents are given in the command line (see the @code{java.lang.instrument} package documentation). The VM has to set the static field @code{VMClassLoader.instrumenter} to this object. The VM should implement the static native methods of the @code{VMInstrumentationImpl} class. 710,724c711,728 When agents are defined, the VM has to call transformers of the @code{InstrumentImpl} object each time a class is loaded, eg a call to @code{VMClassLoader.defineClass}. The @code{InstrumentationImpl} class defines a method that has to be called before reading a class file in the VM. @itemize @bullet @item @code{callTransformers} -- Calls each transformer registered to the @code{InstrumentationImpl} object and returns a new bytecode file. @end itemize No default implementation is provided in gnu classpath for the @code{VMInstrumentationImpl} methods. A default implementation will perhaps be written, but it might break the @code{ClassLoader/VMClassLoader} interface for calling the @code{InstrumentationImpl.callTransformers} when a class byte code is defined with @code{ClassLoader.defineClass}. --- Instrumentation allows to modify the bytecode of a class before it gets read by the VM. In Gnu Classpath, the @code{ClassLoader.defineClass} method calls the @code{VMClassLoader.defineClassWithTransformers} method which first checks if @code{VMClassLoader.instrumenter} is @code{null}. If it's the case, it directly calls @code{VMClassLoader.defineClass}. If it's not the case, the method calls at first the @code{InstrumentationImpl.callTransformers} method, which calls each transformer registered to the @code{InstrumentationImpl} object and returns a new bytecode array. Then, it calls the @code{VMClassLoader.defineClass} method with this new bytecode array. The second use of instrumentation is to redefine a class after it has been loaded by the VM. This is done in the Java application by calling the @code{Instrumentation.redefineClasses} method of the standard interface on a @code{Instrumentation} object. The @code{InstrumentationImpl.redefineClasses} method calls the @code{VMInstrumentationImpl.redefineClasses} native method which must be implemented by the VM. The implementation should call the @code{InstrumentationImpl.callTransformers} method. ___ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches
[commit-cp] classpath ./ChangeLog doc/vmintegration.texinfo
CVSROOT:/cvsroot/classpath Module name:classpath Branch: Changes by: Nicolas Geoffray [EMAIL PROTECTED]06/01/16 13:18:31 Modified files: . : ChangeLog doc: vmintegration.texinfo Log message: 2006-01-16 Nicolas Geoffray [EMAIL PROTECTED] * doc/vmintegration.texinfo: Updated subsection of the java.lang.InstrumentationImpl documentation. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/classpath/classpath/ChangeLog.diff?tr1=1.6080tr2=1.6081r1=textr2=text http://cvs.savannah.gnu.org/viewcvs/classpath/classpath/doc/vmintegration.texinfo.diff?tr1=1.20tr2=1.21r1=textr2=text
Re: [cp-patches] [generics] FYI: New Instrumentation parameter to VMInstrumentationImpl.redefineClasses
Andrew John Hughes wrote: Instrumentation is a 1.5 package feature. It's not part of the 1.4 specification. That's why the files are only in the branch. Nicolas But the branch isn't for 1.5 features as such. It's for stuff that will only compile when used with a compiler supporting the 1.5 features (generics, enums, annotations and a few bits of syntactic sugar). So, if you can actually compile and run all the instrumentation stuff with a 1.4 suite, it should be on HEAD, IMHO. At least, that was my understanding of this and why it's called a generics branch and not a 1.5 branch -- someone correct me if I'm wrong. There are quite a few 1.5 package features on HEAD already. OK, I thought the generics branch was the equivalent of the 1.5 branch of sun. But if it's not the case, I have no problem commiting instrumentation code to HEAD. I do have one question though : the (sun) API of instrumentation has generics code (for example http://java.sun.com/j2se/1.5.0/docs/api/java/lang/instrument/ClassDefinition.html), does it make sense (and I'm OK if you think it does) to modify the API in order to fit for a non-generics code? Nicolas ___ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches
Re: [cp-patches] RFC : modifiers in java/lang/Class
Allright, commited 2005-12-18 Nicolas Geoffray [EMAIL PROTECTED] * java/lang/Class.java (getModifiers): Only returns interesting bits. Jeroen Frijters wrote: Hi Nicolas, Yes it makes sense to filter the relevant bits here instead of at the VM level, please commit. Thanks, Jeroen -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Nicolas Geoffray Sent: Saturday, December 17, 2005 00:05 To: classpath-patches Subject: [cp-patches] RFC : modifiers in java/lang/Class Hi, The access flag of a class might have the synchronized bit set, even if it's not appropriate for a class. The java file attached prints public synchronized as modifiers with jamvm, whereas it prints public with sun. This patch just changes the return of Class.getModifiers to return only interesting bits. OK to commit? 2005-12-17 Nicolas Geoffray [EMAIL PROTECTED] * java/lang/Class.java (getModifiers): Only returns interesting bits. ___ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches
[commit-cp] classpath ./ChangeLog java/lang/Class.java
CVSROOT:/cvsroot/classpath Module name:classpath Branch: Changes by: Nicolas Geoffray [EMAIL PROTECTED]05/12/18 13:03:48 Modified files: . : ChangeLog java/lang : Class.java Log message: 2005-12-18 Nicolas Geoffray [EMAIL PROTECTED] * java/lang/Class.java (getModifiers): Only returns interesting bits. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/classpath/classpath/ChangeLog.diff?tr1=1.5852tr2=1.5853r1=textr2=text http://cvs.savannah.gnu.org/viewcvs/classpath/classpath/java/lang/Class.java.diff?tr1=1.42tr2=1.43r1=textr2=text
[cp-patches] RFC : modifiers in java/lang/Class
Hi, The access flag of a class might have the synchronized bit set, even if it's not appropriate for a class. The java file attached prints public synchronized as modifiers with jamvm, whereas it prints public with sun. This patch just changes the return of Class.getModifiers to return only interesting bits. OK to commit? 2005-12-17 Nicolas Geoffray [EMAIL PROTECTED] * java/lang/Class.java (getModifiers): Only returns interesting bits. import java.io.ObjectStreamClass; import java.lang.reflect.Modifier; public class Serial implements java.io.Serializable{ public static void main(String[]args) throws Exception{ System.out.println(Modifier.toString(Serial.class.getModifiers())); System.out.println(Serial.class.getModifiers()); System.out.println(ObjectStreamClass.lookup(Serial.class).getSerialVersionUID()); } } Index: java/lang/Class.java === RCS file: /cvsroot/classpath/classpath/java/lang/Class.java,v retrieving revision 1.42 diff -u -r1.42 Class.java --- java/lang/Class.java16 Dec 2005 18:06:52 - 1.42 +++ java/lang/Class.java16 Dec 2005 23:03:40 - @@ -836,7 +836,10 @@ */ public int getModifiers() { -return VMClass.getModifiers (this, false); +int mod = VMClass.getModifiers (this, false); +return (mod (Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | + Modifier.FINAL | Modifier.STATIC | Modifier.ABSTRACT | + Modifier.INTERFACE)); } /** ___ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches
Re: [cp-patches] [generics] RFC: instrumentation for defineClasses
I'm committing this in since I had no objection. 2005-12-14 Nicolas Geoffray [EMAIL PROTECTED] * java/lang/ClassLoader (defineClass(String,byte[],int,int,ProtectionDomain)): Calls VMClassLoader.defineClassWithTransformers instead of VMClassLoader.defineClass. * vm/reference/java/lang/VMClassLoader (defineClassWithTransformers): New method. (instrumenter): New Field. Nicolas Geoffray wrote: Hi, I implemented the instrumentation of definition of classes in classpath. With the previous implementation, the vm needed to call transformers, now the call is done in java.lang.ClassLoader.defineClass. This doesn't break the vm interface. The vm implementor needs to fill in VMClassLoader.instrumenter the java.lang.InstrumentationImpl object (or any other implementation, but it should be noted that the VMClassLoader.redefineClassWithTransformers needs the instrumentation object to have a callTransformers method) The drawback of this implementation is that defineClass will allways test if there is an InstrumentationImpl object that is defined. If a vm doesn't want this test, it can still modify the VMClassLoader.redefineClassWithTransformers to be the VMClassLoader.defineClass method. Nicolas 2005-12-09 Nicolas Geoffray [EMAIL PROTECTED] * java/lang/ClassLoader (defineClass(String,byte[],int,int,ProtectionDomain)): Calls VMClassLoader.defineClassWithTransformers instead of VMClassLoader.defineClass. * vm/reference/java/lang/VMClassLoader (defineClassWithTransformers): New method. (instrumenter): New Field. Index: vm/reference/java/lang/VMClassLoader.java === RCS file: /cvsroot/classpath/classpath/vm/reference/java/lang/VMClassLoader.java,v retrieving revision 1.16.2.11 diff -u -r1.16.2.11 VMClassLoader.java --- vm/reference/java/lang/VMClassLoader.java 2 Nov 2005 00:44:15 - 1.16.2.11 +++ vm/reference/java/lang/VMClassLoader.java 9 Dec 2005 10:59:27 - @@ -44,6 +44,8 @@ import java.io.File; import java.io.IOException; +import java.lang.InstrumentationImpl; +import java.lang.instrument.Instrumentation; import java.net.MalformedURLException; import java.net.URL; import java.security.ProtectionDomain; @@ -346,4 +348,41 @@ * for this class. */ static native Class findLoadedClass(ClassLoader cl, String name); + + /** + * The Instrumentation object created by the vm when agents are defined. + */ + static final Instrumentation instrumenter = null; + + /** + * Call the transformers of the possible Instrumentation object + * + * @param loader the initiating loader + * @param name the name of the class + * @param data the data representing the classfile, in classfile format + * @param offset the offset into the data where the classfile starts + * @param len the length of the classfile data in the array + * @param pd the protection domain + * @return the new data representing the classfile + */ + static final Class defineClassWithTransformers(ClassLoader loader, + String name, byte[] data, int offset, int len, ProtectionDomain pd) + { + +if (instrumenter != null) + { +byte[] modifiedData = new byte[len]; +System.arraycopy(data, offset, modifiedData, 0, len); +modifiedData = + ((InstrumentationImpl)instrumenter).callTransformers(loader, name, +null, pd, modifiedData); + +return defineClass(loader, name, modifiedData, 0, modifiedData.length, +pd); + } +else + { +return defineClass(loader, name, data, offset, len, pd); + } + } } Index: java/lang/ClassLoader.java === RCS file: /cvsroot/classpath/classpath/java/lang/ClassLoader.java,v retrieving revision 1.31.2.14 diff -u -r1.31.2.14 ClassLoader.java --- java/lang/ClassLoader.java 2 Nov 2005 00:43:33 - 1.31.2.14 +++ java/lang/ClassLoader.java 9 Dec 2005 10:59:32 - @@ -467,7 +467,9 @@ checkInitialized(); if (domain == null) domain = StaticData.defaultProtectionDomain; -return VMClassLoader.defineClass(this, name, data, offset, len, domain); + +return VMClassLoader.defineClassWithTransformers(this, name, data, offset, +len, domain); } /** ___ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches Index: java/lang/ClassLoader.java === RCS file: /cvsroot/classpath/classpath/java/lang/ClassLoader.java,v retrieving revision 1.31.2.14 diff -u -r1.31.2.14 ClassLoader.java --- java/lang/ClassLoader.java 2 Nov 2005 00:43:33 - 1.31.2.14 +++ java
[cp-patches] [generics] RFC: instrumentation for defineClasses
Hi, I implemented the instrumentation of definition of classes in classpath. With the previous implementation, the vm needed to call transformers, now the call is done in java.lang.ClassLoader.defineClass. This doesn't break the vm interface. The vm implementor needs to fill in VMClassLoader.instrumenter the java.lang.InstrumentationImpl object (or any other implementation, but it should be noted that the VMClassLoader.redefineClassWithTransformers needs the instrumentation object to have a callTransformers method) The drawback of this implementation is that defineClass will allways test if there is an InstrumentationImpl object that is defined. If a vm doesn't want this test, it can still modify the VMClassLoader.redefineClassWithTransformers to be the VMClassLoader.defineClass method. Nicolas 2005-12-09 Nicolas Geoffray [EMAIL PROTECTED] * java/lang/ClassLoader (defineClass(String,byte[],int,int,ProtectionDomain)): Calls VMClassLoader.defineClassWithTransformers instead of VMClassLoader.defineClass. * vm/reference/java/lang/VMClassLoader (defineClassWithTransformers): New method. (instrumenter): New Field. Index: vm/reference/java/lang/VMClassLoader.java === RCS file: /cvsroot/classpath/classpath/vm/reference/java/lang/VMClassLoader.java,v retrieving revision 1.16.2.11 diff -u -r1.16.2.11 VMClassLoader.java --- vm/reference/java/lang/VMClassLoader.java 2 Nov 2005 00:44:15 - 1.16.2.11 +++ vm/reference/java/lang/VMClassLoader.java 9 Dec 2005 10:59:27 - @@ -44,6 +44,8 @@ import java.io.File; import java.io.IOException; +import java.lang.InstrumentationImpl; +import java.lang.instrument.Instrumentation; import java.net.MalformedURLException; import java.net.URL; import java.security.ProtectionDomain; @@ -346,4 +348,41 @@ * for this class. */ static native Class findLoadedClass(ClassLoader cl, String name); + + /** + * The Instrumentation object created by the vm when agents are defined. + */ + static final Instrumentation instrumenter = null; + + /** + * Call the transformers of the possible Instrumentation object + * + * @param loader the initiating loader + * @param name the name of the class + * @param data the data representing the classfile, in classfile format + * @param offset the offset into the data where the classfile starts + * @param len the length of the classfile data in the array + * @param pd the protection domain + * @return the new data representing the classfile + */ + static final Class defineClassWithTransformers(ClassLoader loader, + String name, byte[] data, int offset, int len, ProtectionDomain pd) + { + +if (instrumenter != null) + { +byte[] modifiedData = new byte[len]; +System.arraycopy(data, offset, modifiedData, 0, len); +modifiedData = + ((InstrumentationImpl)instrumenter).callTransformers(loader, name, +null, pd, modifiedData); + +return defineClass(loader, name, modifiedData, 0, modifiedData.length, +pd); + } +else + { +return defineClass(loader, name, data, offset, len, pd); + } + } } Index: java/lang/ClassLoader.java === RCS file: /cvsroot/classpath/classpath/java/lang/ClassLoader.java,v retrieving revision 1.31.2.14 diff -u -r1.31.2.14 ClassLoader.java --- java/lang/ClassLoader.java 2 Nov 2005 00:43:33 - 1.31.2.14 +++ java/lang/ClassLoader.java 9 Dec 2005 10:59:32 - @@ -467,7 +467,9 @@ checkInitialized(); if (domain == null) domain = StaticData.defaultProtectionDomain; -return VMClassLoader.defineClass(this, name, data, offset, len, domain); + +return VMClassLoader.defineClassWithTransformers(this, name, data, offset, +len, domain); } /** ___ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches
Re: [cp-patches] [generics] Patch: FYI: javadoc fixes in java.lang.instrument
Hi Tom Tom Tromey wrote: I'm checking this in on the generics branch. I found a couple minor javadoc problems in the new java.lang.instrument code. Fixed as appended. Thx for reading after :) Cheers, Nicolas ___ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches
Re: [cp-patches] [generics] RFC : implementation of jjava.lang.instrument package
Hi Christian, Christian Thalinger wrote: On Fri, 2005-12-02 at 12:22 +0100, Nicolas Geoffray wrote: gnu/java/lang/instrument. Would you like InstrumentationImpl to be in vm/reference/java/lang/InsutrumentationImpl? This sounds weird. We could also make the callTransformers method public. I think it's very helpful for vm implementors that all vm interface stuff is _only_ located in vm/reference. Just my 2 cents... I couldn't agree more. What surprised me is not the vm/reference/* emplacement Mark suggested, but that VMInstrumentationImpl and Instrumentation had to go in the java.lang package, whereas I was more thinking to gnu.java.lang package. But Mark is right when he says it will be easier with security and package private method issues to have the files in the java.lang package. Cheers, Nicolas ___ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches
[cp-patches] [generics] FYI: New Instrumentation parameter to VMInstrumentationImpl.redefineClasses
Here's a fix that eases implementation of the VMInstrumentationImpl.redefineClasses method. The VM might not want to keep the Instrument object, therefore it must be given explicitely to the VMInstrumentationImpl.redefineClasses method 2005-12-04 Nicolas Geoffray [EMAIL PROTECTED] * vm/reference/java/lang/VMInstrumentationImpl.java (redefineClasses): Added an extra parameter of type java.lang.instrument.Instrument. *java/lang/InstrumentationImpl.java (redefineClasses): Added the Instrumentation object to the arguments of VMInstrumentationImpl.redefineClasses call. Index: java/lang/InstrumentationImpl.java === RCS file: /cvsroot/classpath/classpath/java/lang/Attic/InstrumentationImpl.java,v retrieving revision 1.1.2.1 diff -u -r1.1.2.1 InstrumentationImpl.java --- java/lang/InstrumentationImpl.java 3 Dec 2005 15:26:35 - 1.1.2.1 +++ java/lang/InstrumentationImpl.java 4 Dec 2005 13:01:02 - @@ -154,7 +154,7 @@ if (!isRedefineClassesSupported()) throw new UnsupportedOperationException(); -VMInstrumentationImpl.redefineClasses(definitions); +VMInstrumentationImpl.redefineClasses(this, definitions); } Index: vm/reference/java/lang/VMInstrumentationImpl.java === RCS file: /cvsroot/classpath/classpath/vm/reference/java/lang/Attic/VMInstrumentationImpl.java,v retrieving revision 1.1.2.1 diff -u -r1.1.2.1 VMInstrumentationImpl.java --- vm/reference/java/lang/VMInstrumentationImpl.java 3 Dec 2005 15:26:35 - 1.1.2.1 +++ vm/reference/java/lang/VMInstrumentationImpl.java 4 Dec 2005 13:01:20 - @@ -40,6 +40,7 @@ package java.lang; import java.lang.instrument.ClassDefinition; +import java.lang.instrument.Instrumentation; /** * @author Nicolas Geoffray ([EMAIL PROTECTED]) @@ -59,6 +60,7 @@ * Redefines classes given as parameters. The method has to call * the callTransformers from InstrumentationImpl * + * @param inst an instrumentation object * @param definitions an array of bytecode-class correspondance * * @throws ClassNotFoundException if a class cannot be found @@ -74,7 +76,8 @@ * classes * @throws LinkageError if a linkage error occurs */ - static native void redefineClasses(ClassDefinition[] definitions); + static native void redefineClasses(Instrumentation inst, + ClassDefinition[] definitions); /** * Get all the classes loaded by the JVM. ___ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches
[cp-patches] RFC : Instrumentation in the vm integration guide
Hi, Here's a small documentation on how to use the instrumentation functionnality in gnu classpath generics for vm implementers. I added at the end that default implementation might break the ClassLoader/VMClassLoader interface. 2005-12-04 Nicolas Geoffray [EMAIL PROTECTED] * doc/vmintegration.texinfo: Added subsection in the classpath hooks for the VMInstrumentationImpl class. Index: doc/vmintegration.texinfo === RCS file: /cvsroot/classpath/classpath/doc/vmintegration.texinfo,v retrieving revision 1.19 diff -u -r1.19 vmintegration.texinfo --- doc/vmintegration.texinfo 15 Jul 2005 09:04:46 - 1.19 +++ doc/vmintegration.texinfo 4 Dec 2005 15:15:52 - @@ -226,6 +226,7 @@ * java.lang.VMRuntime:: * java.lang.VMString:: * java.lang.VMThread:: +* java.lang.VMInstrumentationImpl:: @end menu @node java.lang.VMClass, java.lang.VMObject ,java.lang,java.lang @@ -607,7 +608,7 @@ A VM may implement this differently by implementing this method, which is @code{static} and the only one in @code{VMString}. [EMAIL PROTECTED] java.lang.VMThread,, java.lang.VMString, java.lang [EMAIL PROTECTED] java.lang.VMThread,java.lang.VMInstrumentationImpl, java.lang.VMString, java.lang @subsection @code{java.lang.VMThread} @code{VMThread} provides the link between Java's threads and the platform @@ -681,7 +682,43 @@ frames in the thread. This depends on the deprecated method @code{suspend()} having returned true, and is thus deprecated as a result. @end itemize [EMAIL PROTECTED] itemize + [EMAIL PROTECTED] java.lang.VMInstrumentationImpl,, java.lang.VMThread, java.lang [EMAIL PROTECTED] @code{java.lang.VMInstrumentationImpl} + +The @code{java.lang.VMInstrumentationImpl} and [EMAIL PROTECTED] provides an implementation of the [EMAIL PROTECTED] interface. This interface is for java +1.5 and is only in the generics branch. +A @code{InstrumentationImpl} object should be given to any agent +given in the command line (see the @code{java.lang.instrument} package +documentation). A VM has to implement the static native methods of the [EMAIL PROTECTED] class. + [EMAIL PROTECTED] @bullet [EMAIL PROTECTED] @code{isRedefineClassesSupported()} -- Returns if the JVM supports +class redefinition. [EMAIL PROTECTED] @code{redefineClasses()} -- Gives a set of classes with new bytecodes. +The VM must redefine the classes by reading the new bytecodes. [EMAIL PROTECTED] @code{getAllLoadedClass()} -- Returns an array of all loaded classes. [EMAIL PROTECTED] @code{getInitiatedClass()} -- Returns an array of all classes loaded +by a specific class loader. [EMAIL PROTECTED] @code{getObjectSize()} -- Gives the size of an object. [EMAIL PROTECTED] itemize + +When agents are defined, the VM has to call transformers of the [EMAIL PROTECTED] object each time a class is loaded, eg a call to [EMAIL PROTECTED] The @code{InstrumentationImpl} class defines +a method that has to be called before reading a class file in the VM. + [EMAIL PROTECTED] @bullet [EMAIL PROTECTED] @code{callTransformers} -- Calls each transformer registered to +the @code{InstrumentationImpl} object and returns a new bytecode file. [EMAIL PROTECTED] itemize + +No default implementation is provided in gnu classpath for the [EMAIL PROTECTED] method. A default implementation will perhaps +be written, but it might break the @code{ClassLoader/VMClassLoader} interface. @node gnu.classpath, java.util, java.lang, Classpath Hooks @section @code{gnu.classpath} ___ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches
Re: [cp-patches] FYI : Instrumentation in the vm integration guide
Hi Mark Maybe explicitly say for calling the @code{InstrumentationImpl.callTransformers} when a class byte code is defined with @code{ClassLoader.defineClass} So the vm implementer knows this is their job at the moment. Allright added. I'm committing this in the main branch. 2005-12-04 Nicolas Geoffray [EMAIL PROTECTED] * doc/vmintegration.texinfo: Added subsection in the classpath hooks for the VMInstrumentationImpl class. Index: doc/vmintegration.texinfo === RCS file: /cvsroot/classpath/classpath/doc/vmintegration.texinfo,v retrieving revision 1.19 diff -u -r1.19 vmintegration.texinfo --- doc/vmintegration.texinfo 15 Jul 2005 09:04:46 - 1.19 +++ doc/vmintegration.texinfo 4 Dec 2005 20:45:03 - @@ -226,6 +226,7 @@ * java.lang.VMRuntime:: * java.lang.VMString:: * java.lang.VMThread:: +* java.lang.VMInstrumentationImpl:: @end menu @node java.lang.VMClass, java.lang.VMObject ,java.lang,java.lang @@ -607,7 +608,7 @@ A VM may implement this differently by implementing this method, which is @code{static} and the only one in @code{VMString}. [EMAIL PROTECTED] java.lang.VMThread,, java.lang.VMString, java.lang [EMAIL PROTECTED] java.lang.VMThread,java.lang.VMInstrumentationImpl, java.lang.VMString, java.lang @subsection @code{java.lang.VMThread} @code{VMThread} provides the link between Java's threads and the platform @@ -682,6 +683,45 @@ having returned true, and is thus deprecated as a result. @end itemize @end itemize + [EMAIL PROTECTED] java.lang.VMInstrumentationImpl,, java.lang.VMThread, java.lang [EMAIL PROTECTED] @code{java.lang.VMInstrumentationImpl} + +The @code{java.lang.VMInstrumentationImpl} and [EMAIL PROTECTED] provides an implementation of the [EMAIL PROTECTED] interface. This interface is for java +1.5 and is only in the generics branch. +A @code{InstrumentationImpl} object should be given to any agent +given in the command line (see the @code{java.lang.instrument} package +documentation). A VM has to implement the static native methods of the [EMAIL PROTECTED] class. + [EMAIL PROTECTED] @bullet [EMAIL PROTECTED] @code{isRedefineClassesSupported()} -- Returns true if the JVM supports +class redefinition. [EMAIL PROTECTED] @code{redefineClasses()} -- Gives a set of classes with new bytecodes. +The VM must redefine the classes by reading the new bytecodes. [EMAIL PROTECTED] @code{getAllLoadedClass()} -- Returns an array of all loaded classes. [EMAIL PROTECTED] @code{getInitiatedClass()} -- Returns an array of all classes loaded +by a specific class loader. [EMAIL PROTECTED] @code{getObjectSize()} -- Gives the size of an object. [EMAIL PROTECTED] itemize + +When agents are defined, the VM has to call transformers of the [EMAIL PROTECTED] object each time a class is loaded, eg a call to [EMAIL PROTECTED] The @code{InstrumentationImpl} class defines +a method that has to be called before reading a class file in the VM. + [EMAIL PROTECTED] @bullet [EMAIL PROTECTED] @code{callTransformers} -- Calls each transformer registered to +the @code{InstrumentationImpl} object and returns a new bytecode file. [EMAIL PROTECTED] itemize + +No default implementation is provided in gnu classpath for the [EMAIL PROTECTED] methods. A default implementation will perhaps +be written, but it might break the @code{ClassLoader/VMClassLoader} interface +for calling the @code{InstrumentationImpl.callTransformers} when a class byte +code is defined with @code{ClassLoader.defineClass}. @node gnu.classpath, java.util, java.lang, Classpath Hooks @section @code{gnu.classpath} ___ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches
[commit-cp] classpath ./ChangeLog vm/reference/java/lang/VM... [generics-branch]
CVSROOT:/cvsroot/classpath Module name:classpath Branch: generics-branch Changes by: Nicolas Geoffray [EMAIL PROTECTED]05/12/04 13:19:39 Modified files: . : ChangeLog vm/reference/java/lang: VMInstrumentationImpl.java java/lang : InstrumentationImpl.java Log message: 2005-12-04 Nicolas Geoffray [EMAIL PROTECTED] * vm/reference/java/lang/VMInstrumentationImpl.java (redefineClasses): Added an extra parameter of type java.lang.instrument.Instrument. * java/lang/InstrumentationImpl.java (redefineClasses): Added the Instrumentation object to the arguments of VMInstrumentationImpl.redefineClasses call. CVSWeb URLs: http://savannah.gnu.org/cgi-bin/viewcvs/classpath/classpath/ChangeLog.diff?only_with_tag=generics-branchtr1=1.2386.2.185tr2=1.2386.2.186r1=textr2=text http://savannah.gnu.org/cgi-bin/viewcvs/classpath/classpath/vm/reference/java/lang/VMInstrumentationImpl.java.diff?only_with_tag=generics-branchtr1=1.1.2.1tr2=1.1.2.2r1=textr2=text http://savannah.gnu.org/cgi-bin/viewcvs/classpath/classpath/java/lang/InstrumentationImpl.java.diff?only_with_tag=generics-branchtr1=1.1.2.1tr2=1.1.2.2r1=textr2=text
Re: [cp-patches] [generics] FYI : implementation of java.lang.instrument package
Instrumentation implementation is commited (a little too fast, usage of -m instead of -F gives a nice log message /tmp/cvseljWQl, don't know if it can be corrected. Sorry admins :() 2005-12-03 Nicolas Geoffray [EMAIL PROTECTED] * java/lang/instrument: New directory. * java/lang/instrument/ClassDefinition.java: New file. * java/lang/instrument/ClassFileTransformer.java: New file. * java/lang/instrument/IllegalClassFormatException.java: New file. * java/lang/instrument/Instrumentation.java: New file. * java/lang/instrument/UnmodifiableClassException.java: New file. * java/lang/InstrumentationImpl.java: New file. * vm/reference/java/lang/VMInstrumentationImpl.java: New file. ___ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches
[commit-cp] classpath ./ChangeLog java/lang/instrument/Clas... [generics-branch]
CVSROOT:/cvsroot/classpath Module name:classpath Branch: generics-branch Changes by: Nicolas Geoffray [EMAIL PROTECTED]05/12/03 15:26:36 Modified files: . : ChangeLog Added files: java/lang/instrument: ClassDefinition.java ClassFileTransformer.java IllegalClassFormatException.java Instrumentation.java UnmodifiableClassException.java java/lang : InstrumentationImpl.java vm/reference/java/lang: VMInstrumentationImpl.java Log message: /tmp/cvseljWQl CVSWeb URLs: http://savannah.gnu.org/cgi-bin/viewcvs/classpath/classpath/java/lang/instrument/ClassDefinition.java?only_with_tag=generics-branchrev=1.1.2.1 http://savannah.gnu.org/cgi-bin/viewcvs/classpath/classpath/java/lang/instrument/ClassFileTransformer.java?only_with_tag=generics-branchrev=1.1.2.1 http://savannah.gnu.org/cgi-bin/viewcvs/classpath/classpath/java/lang/instrument/IllegalClassFormatException.java?only_with_tag=generics-branchrev=1.1.2.1 http://savannah.gnu.org/cgi-bin/viewcvs/classpath/classpath/java/lang/instrument/Instrumentation.java?only_with_tag=generics-branchrev=1.1.2.1 http://savannah.gnu.org/cgi-bin/viewcvs/classpath/classpath/java/lang/instrument/UnmodifiableClassException.java?only_with_tag=generics-branchrev=1.1.2.1 http://savannah.gnu.org/cgi-bin/viewcvs/classpath/classpath/java/lang/InstrumentationImpl.java?only_with_tag=generics-branchrev=1.1.2.1 http://savannah.gnu.org/cgi-bin/viewcvs/classpath/classpath/vm/reference/java/lang/VMInstrumentationImpl.java?only_with_tag=generics-branchrev=1.1.2.1 http://savannah.gnu.org/cgi-bin/viewcvs/classpath/classpath/ChangeLog.diff?only_with_tag=generics-branchtr1=1.2386.2.184tr2=1.2386.2.185r1=textr2=text
Re: [cp-patches] [generics] RFC : implementation of jjava.lang.instrument package
Hi Mark, Mark Wielaard wrote: My idea was even that a VM might only want to have one redefine prepare/apply cycle running at the same time. Then it can easily cleanup anything not used. But this might be optimizing for an unusual case. We can probably assume that transformers will actually transform correctly. You're deleting all shared code I came up with :) I switched to your idea because it reduces the number of native methods. Aha. Sorry I missed the dual nature of the ClassFileTransFormer.transform() method. I see you documented this in your original patch. In that case I really do think we should move these to vm/reference/java/lang and make this method package private. Which method? callTransformers? It's a method from the InstrumentationImpl class, therefore it's in gnu/java/lang/instrument. Would you like InstrumentationImpl to be in vm/reference/java/lang/InsutrumentationImpl? This sounds weird. We could also make the callTransformers method public. Right, I see we need to break the VM interface for this :{ Probably best not to do that for the first release (0.20) but lets suggest how we would like to change the interface for 0.21 so runtime implementers can prepare and scream about it. On the other hand this is the generics branch only, not very many VMs depend on it yet. But not very urgent I guess before we have this working with at least one VM. I'm working on it (the jnjvm can now execute with the generics branch, yeah :)). OK for making suggestions, where should it be written? Just make a new paragraph for Instrumentation. Then mention that it currently only is on the generics branch since it uses some new language features. OK then. Cheers, Nicolas ___ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches
Re: [cp-patches] [generics] RFC : implementation of jjava.lang.instrument package
Mark Wielaard wrote: Yes, but it makes it easier to share code with ClassLoader and VMClassLoader if we do this. Then callTransformers doesn't have to be public, but can just be package private. Then we don't have to worry about whether or not someone can get insecure access to a IntrumentationImpl (although I admit that is not very likely). It just seems more natural to me to have all implementation classes in the same package because they seem very related. Allright then, VMInstrumentationImpl and InstrumentationImpl are in vm/reference/java/lang Last RFC, and I'm commiting this in 2005-12-02 Nicolas Geoffray [EMAIL PROTECTED] * java/lang/instrument: New directory. * java/lang/instrument/ClassDefinition.java: New file. * java/lang/instrument/ClassFileTransformer.java: New file. * java/lang/instrument/IllegalClassFormatException.java: New file. * java/lang/instrument/Instrumentation.java: New file. * java/lang/instrument/UnmodifiableClassException.java: New file. * vm/reference/java/lang/InstrumentationImpl.java: New file. * vm/reference/java/lang/VMInstrumentationImpl.java: New file. instrument.tar.gz Description: GNU Zip compressed data ___ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches
Re: [cp-patches] [generics] RFC : implementation of java.lang.instrument package
Nicolas Where this class should be : Nicolas gnu/java/lang/instrument/InstrumentationImpl.java? Yes, that is the correct package to use. The name of the class is less strictly defined by Classpath, but that name sounds fine to me. Yes, that name is OK. I don't know how much we can actually share between runtimes though. The interface is pretty minimal already, so a split between VMInstrumentationImpl and InstrumentationImpl that calls the VM class seems overkill. The InstrumentationImpl.getObjectSize is clearly a native for vm. And we also need a native redefineClass(Class, byte[]). If we don't provide a VMInstrumentationImpl class, would these method be native in InstrumentationImpl? (I thought vm implementors only had to care about vm/reference/* files?) Do you think you can come up with something that can easily be shared by runtimes? Maybe you could hook into the default ClassLoader.defineClass() implementation to implement this? Because it's the vm that parses arguments, it knowns if the application does instrumentation. Therefore, if it supports redefining classes, it can set a flag or change definition of VMClassLoader.defineClass. The vm then creates an InstrumentationImpl object and calls premain. The VMClassLoader.defineClass will be changed to call a private InstrumentationImpl.defineClass method. This method will then call each transformer. Does that sound correct to you? This way I don't modify ClassLoader.defineClass. Cheers, Nicolas ___ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches
[cp-patches] [generics] RFC : implementation of java.lang.instrument package
Hi everyone, I implemented (implement is not really appropriate as it's minor files with interfaces and exceptions) the java.lang.instrument.* files of the 1.5 API. Implementation is not complete. It needs a class extending the Instrumentation class (see http://java.sun.com/j2se/1.5.0/docs/api/). Where this class should be : gnu/java/lang/instrument/InstrumentationImpl.java? Cheers, Nicolas 2005-11-23 Nicolas Geoffray [EMAIL PROTECTED] * java/lang/instrument: New directory. * java/lang/instrument/ClassDefinition.java: New file. * java/lang/instrument/ClassFileTransformer.java: New file. * java/lang/instrument/IllegalClassFormatException.java: New file. * java/lang/instrument/Instrumentation.java: New file. * java/lang/instrument/UnmodifiableClassException.java: New file. /* ClassDefinition.java -- Class that binds a class with a new class file Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. GNU Classpath is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Classpath is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Classpath; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Linking this library statically or dynamically with other modules is making a combined work based on this library. Thus, the terms and conditions of the GNU General Public License cover the whole combination. As a special exception, the copyright holders of this library give you permission to link this library with independent modules to produce an executable, regardless of the license terms of these independent modules, and to copy and distribute the resulting executable under terms of your choice, provided that you also meet, for each linked independent module, the terms and conditions of the license of that module. An independent module is a module which is not derived from or based on this library. If you modify this library, you may extend this exception to your version of the library, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ package java.lang.instrument; /** * This class binds a class that will be redefined with a new * class file. * * @author Nicolas Geoffray ([EMAIL PROTECTED]) * @see Instrumentation#redefineClasses(java.lang.instrument.ClassDefinition[]) * @since 1.5 */ public final class ClassFileTransformer { /* The class it's related */ private Class theClass; /* The new bytecode of theClass */ private byte[] theClassFile; /** * @param theClass the Class that will be redefined * @param theClassFile the new class file * @throws NullPointerException if one of the argument is null */ ClassDefinition(Class? theClass, byte[] theClassFile){ if(theClass == null || theClassFile == null) throw new NullPointerException(); this.theClass = theClass; this.theClassFile = theClassFile; } /** * @return the Class */ public Class? getDefinitionClass(){ return theClass; } /** * @return the bytes */ public byte[] getDefinitionClassFile(){ return theClassFile; } } /* ClassFileTransformer.java -- Implementation of this interface is used by an agent to transform class files. Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. GNU Classpath is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Classpath is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Classpath; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Linking this library statically or dynamically with other modules is making a combined work based on this library. Thus, the terms and conditions of the GNU General Public License cover the whole combination. As a special exception, the copyright holders of this library give you permission to link this library with independent modules to produce an executable, regardless
Re: [cp-patches] RFC: implementation of getPackage for the vmreference
Mark Wielaard wrote: Hi, On Sun, 2005-10-23 at 16:17 +0200, Jeroen Frijters wrote: Nicolas Geoffray wrote: Mark are you OK with the changes? I would like to see this go in before 0.19. After 0.19 (based on feedback from other VM implementers) we should consider making getBootPackages native so that they will be able to use the reference VMClassLoader as is. Agreed. This looks fine. Nicolas can you add a little note about this (and the feedback we want) for the NEWS file? Great! I'm committing this in. 2005-10-21 Nicolas Geoffray [EMAIL PROTECTED] Reported by: Gael Thomas [EMAIL PROTECTED] * vm/reference/java/lang/VMClassLoader.java: Added new definedPackages field to store packages loaded by the bootstrap classloader. Added new static initializer to create all packages which names are returned by getBootPackages (getBootPackages): new private method. Helper to get as a String[] the native package names (getPackage): uses the new definedPackages field (getPackages): uses the new definedPackages field * java/lang/Class.java: (getPackage): if the classloader of the class is null then call VMClassLoader.getPackage Nicolas Index: vm/reference/java/lang/VMClassLoader.java === RCS file: /cvsroot/classpath/classpath/vm/reference/java/lang/VMClassLoader.java,v retrieving revision 1.32 diff -u -r1.32 VMClassLoader.java --- vm/reference/java/lang/VMClassLoader.java 21 Oct 2005 10:47:17 - 1.32 +++ vm/reference/java/lang/VMClassLoader.java 28 Oct 2005 08:35:47 - @@ -40,6 +40,7 @@ package java.lang; import gnu.classpath.SystemProperties; +import gnu.classpath.Configuration; import java.io.File; import java.io.IOException; @@ -63,6 +64,48 @@ */ final class VMClassLoader { + + + /** packages loaded by the bootstrap class loader */ + static final HashMap definedPackages = new HashMap(); + + /** + * Converts the array string of native package names to + * Packages. The packages are then put into the + * definedPackages hashMap + */ + static + { +String[] packages = getBootPackages(); + +if( packages != null) + { +String specName = + SystemProperties.getProperty(java.specification.name); +String vendor = + SystemProperties.getProperty(java.specification.vendor); +String version = + SystemProperties.getProperty(java.specification.version); + +Package p; + +for(int i = 0; i packages.length; i++) + { +p = new Package(packages[i], + specName, + vendor, + version, + GNU Classpath, + GNU, + Configuration.CLASSPATH_VERSION, + null); + +definedPackages.put(packages[i], p); + } + } + } + + /** * Helper to define a class using a string of bytes. This assumes that * the security checks have already been performed, if necessary. @@ -190,29 +233,41 @@ return v.elements(); } + /** - * Helper to get a package from the bootstrap class loader. The default - * implementation of returning null may be adequate, or you may decide - * that this needs some native help. + * Returns a String[] of native package names. The default + * implementation returns an empty array, or you may decide + * this needs native help. + */ + private static String[] getBootPackages() + { +return new String[0]; + } + + + /** + * Helper to get a package from the bootstrap class loader. * * @param name the name to find * @return the named package, if it exists */ static Package getPackage(String name) { -return null; +return (Package)definedPackages.get(name); } + + /** - * Helper to get all packages from the bootstrap class loader. The default - * implementation of returning an empty array may be adequate, or you may - * decide that this needs some native help. + * Helper to get all packages from the bootstrap class loader. * * @return all named packages, if any exist */ static Package[] getPackages() { -return new Package[0]; +Package[] packages = new Package[definedPackages.size()]; +definedPackages.values().toArray(packages); +return packages; } /** Index: java/lang/Class.java === RCS file: /cvsroot/classpath/classpath/java/lang/Class.java,v retrieving revision 1.40 diff -u -r1.40 Class.java --- java/lang/Class.java15 Sep 2005 14:42:36 - 1.40 +++ java/lang/Class.java28 Oct 2005 08:37:34 - @@ -594,7 +594,8 @@ ClassLoader cl = getClassLoader(); if (cl != null
Re: [cp-patches] RFC: implementation of getPackage for the vmreference
Sorry, wrong changelog. Here it is. 2005-10-28 Nicolas Geoffray [EMAIL PROTECTED] Reported by: Gael Thomas [EMAIL PROTECTED] * NEWS : added entry about new implementation of VMClassLoader.getPackage(s), and new method VMClassLoader.getBootPackages * vm/reference/java/lang/VMClassLoader.java: Added new definedPackages field to store packages loaded by the bootstrap classloader. Added new static initializer to create all packages which names are returned by getBootPackages (getBootPackages): new private method. Helper to get as a String[] the native package names (getPackage): uses the new definedPackages field (getPackages): uses the new definedPackages field * java/lang/Class.java: (getPackage): if the classloader of the class is null then call VMClassLoader.getPackage Index: vm/reference/java/lang/VMClassLoader.java === RCS file: /cvsroot/classpath/classpath/vm/reference/java/lang/VMClassLoader.java,v retrieving revision 1.32 diff -u -r1.32 VMClassLoader.java --- vm/reference/java/lang/VMClassLoader.java 21 Oct 2005 10:47:17 - 1.32 +++ vm/reference/java/lang/VMClassLoader.java 28 Oct 2005 08:35:47 - @@ -40,6 +40,7 @@ package java.lang; import gnu.classpath.SystemProperties; +import gnu.classpath.Configuration; import java.io.File; import java.io.IOException; @@ -63,6 +64,48 @@ */ final class VMClassLoader { + + + /** packages loaded by the bootstrap class loader */ + static final HashMap definedPackages = new HashMap(); + + /** + * Converts the array string of native package names to + * Packages. The packages are then put into the + * definedPackages hashMap + */ + static + { +String[] packages = getBootPackages(); + +if( packages != null) + { +String specName = + SystemProperties.getProperty(java.specification.name); +String vendor = + SystemProperties.getProperty(java.specification.vendor); +String version = + SystemProperties.getProperty(java.specification.version); + +Package p; + +for(int i = 0; i packages.length; i++) + { +p = new Package(packages[i], + specName, + vendor, + version, + GNU Classpath, + GNU, + Configuration.CLASSPATH_VERSION, + null); + +definedPackages.put(packages[i], p); + } + } + } + + /** * Helper to define a class using a string of bytes. This assumes that * the security checks have already been performed, if necessary. @@ -190,29 +233,41 @@ return v.elements(); } + /** - * Helper to get a package from the bootstrap class loader. The default - * implementation of returning null may be adequate, or you may decide - * that this needs some native help. + * Returns a String[] of native package names. The default + * implementation returns an empty array, or you may decide + * this needs native help. + */ + private static String[] getBootPackages() + { +return new String[0]; + } + + + /** + * Helper to get a package from the bootstrap class loader. * * @param name the name to find * @return the named package, if it exists */ static Package getPackage(String name) { -return null; +return (Package)definedPackages.get(name); } + + /** - * Helper to get all packages from the bootstrap class loader. The default - * implementation of returning an empty array may be adequate, or you may - * decide that this needs some native help. + * Helper to get all packages from the bootstrap class loader. * * @return all named packages, if any exist */ static Package[] getPackages() { -return new Package[0]; +Package[] packages = new Package[definedPackages.size()]; +definedPackages.values().toArray(packages); +return packages; } /** Index: java/lang/Class.java === RCS file: /cvsroot/classpath/classpath/java/lang/Class.java,v retrieving revision 1.40 diff -u -r1.40 Class.java --- java/lang/Class.java15 Sep 2005 14:42:36 - 1.40 +++ java/lang/Class.java28 Oct 2005 08:37:34 - @@ -594,7 +594,8 @@ ClassLoader cl = getClassLoader(); if (cl != null) return cl.getPackage(getPackagePortion(getName())); -return null; +else + return VMClassLoader.getPackage(getPackagePortion(getName())); } /** Index: NEWS === RCS file: /cvsroot/classpath/classpath/NEWS,v retrieving revision 1.99 diff -u -r1.99 NEWS --- NEWS21 Oct 2005 18:13:39 - 1.99 +++ NEWS28 Oct 2005 08:37:43 - @@ -16,6 +16,14 @@ It can flatten graphs
Re: [cp-patches] RFC: implementation of getPackage for the vmreference
Hi Mark - Please make the change log entries full sentences starting with a capital letter, ending with a dot. - Please commit a change like this in one go that makes relating the commit messages to the actual change a little easier. So in this case: cvs commit ChangeLog NEWS java/lang/Class.java \ vm/reference/java/lang/VMClassLoader.java Allright, I will get used to it :). Thanks for the tips! (and for supervising it) Cheers, Mark Nicolas ___ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches
Re: Interruption of InterruptibleChannel methods
Hi Tom, Nicolas I have the feeling that something has to be done inside gnu Nicolas classpath in order for a a vm to correctly deal with the Nicolas interruption of a thread inside an InterruptibleChannel Nicolas method. At least in the unix ports of libgcj, Thread.interrupt sends a signal to the target thread, the idea being that this will interrupt any blocking I/O operation there. I saw the implementation, the signal handler does nothing, and the method that can receive the signal checks the thread interrupt state. What if the java method that was executing the i/o operation is not part of an InterruptibleChannel class? Does gcj interrupt it too, or does it mask the signal? Furthermore, a developper that creates its own class extending the InterruptibleChannel and has its own native calls (it doesn't use the gcj native implementation of i/o operations), do we (vm implementors) have to deal with it, in order, to have the interrupt thing going well with it? Nicolas Is this kind of discussion present elsewhere? I didn't find Nicolas it in the archives. And the docs in gnu classpath and vms Nicolas seem like forgiving the issue. This requirement (if it is one -- gcj goes its own way for the native code and so I can't really speak for Classpath here) would be a great addition to the VM integration documentation. Apparently, the merge between gnu classpath and gcj doesn't concern native code. I guess it would be easier if this interrupt thing could be in classpath. Has anyone allready looked at it? Cheers, Nicolas ___ Classpath mailing list Classpath@gnu.org http://lists.gnu.org/mailman/listinfo/classpath
[commit-cp] classpath/vm/reference/java/lang VMClassLoader....
CVSROOT:/cvsroot/classpath Module name:classpath Branch: Changes by: Nicolas Geoffray [EMAIL PROTECTED]05/10/28 09:27:55 Modified files: vm/reference/java/lang: VMClassLoader.java Log message: 2005-10-28 Nicolas Geoffray [EMAIL PROTECTED] Reported by: Gael Thomas [EMAIL PROTECTED] * NEWS : added entry about new implementation of VMClassLoader.getPackage(s), and new method VMClassLoader.getBootPackages * vm/reference/java/lang/VMClassLoader.java: Added new definedPackages field to store packages loaded by the bootstrap classloader. Added new static initializer to create all packages which names are returned by getBootPackages (getBootPackages): new private method. Helper to get as a String[] the native package names (getPackage): uses the new definedPackages field (getPackages): uses the new definedPackages field * java/lang/Class.java: (getPackage): if the classloader of the class is null then call VMClassLoader.getPackage CVSWeb URLs: http://savannah.gnu.org/cgi-bin/viewcvs/classpath/classpath/vm/reference/java/lang/VMClassLoader.java.diff?tr1=1.32tr2=1.33r1=textr2=text
[cp-patches] RFC: implementation of getPackage for the vm reference
Hi all, This patch was written when we wanted to test our vm and gnu classpath with jonas. Jonas complained (crashed) because it got a null package for a system class. This patch corrects the issue, and should be adequate for all vms. A new hashmap is added to store the bootstrap classloader's packages. A new method is defined inside VMClassLoader, called getVMPackage. This method shall only be called by Class.getPackage when the class' classloader is null. It looks for the package in definedPackages, and adds if it's not found. Therefore, only a system class can add a package to definedPackages. The VMClassLoader.getPackage method only looks for the package, it doesn't add one. 2005-10-21 Nicolas Geoffray [EMAIL PROTECTED] Reported by: Gael Thomas [EMAIL PROTECTED] * vm/reference/java/lang/VMClassLoader.java: Added new definedPackages field to store packages loaded by the bootstrap classloader (getVMPackage): new method. Finds or adds a package. Shall only be called by Class.getPackage (getPackage): uses the new definedPackages field (getPackages): uses the new definedPackages field * java/lang/Class.java: (getPackage): if the classloader of the class is null then call VMClassLoader.getVMPackage Nicolas Index: vm/reference/java/lang/VMClassLoader.java === RCS file: /cvsroot/classpath/classpath/vm/reference/java/lang/VMClassLoader.java,v retrieving revision 1.32 diff -u -r1.32 VMClassLoader.java --- vm/reference/java/lang/VMClassLoader.java 21 Oct 2005 10:47:17 - 1.32 +++ vm/reference/java/lang/VMClassLoader.java 21 Oct 2005 21:03:37 - @@ -40,6 +40,7 @@ package java.lang; import gnu.classpath.SystemProperties; +import gnu.classpath.Configuration; import java.io.File; import java.io.IOException; @@ -190,29 +191,75 @@ return v.elements(); } + + /** packages loaded by the bootstrap class loader */ + static final HashMap definedPackages = new HashMap(); + + /** - * Helper to get a package from the bootstrap class loader. The default - * implementation of returning null may be adequate, or you may decide - * that this needs some native help. + * Helper to get a package from the bootstrap class loader. * * @param name the name to find * @return the named package, if it exists */ static Package getPackage(String name) { -return null; +synchronized(definedPackages) + { +return (Package)definedPackages.get(name); + } + } + + + /** + * Helper to find/add a package to the bootstrap class loader. + * This method shall only be called by Class.getPackage() + * + * @param name the name to find/add + * @return the named package, if it exists or can be created + */ + static final Package getVMPackage(String name) + { + +// name is empty for primitive types +if (name == ) return null; + +Package p = getPackage(name); + +if (p == null) + { +p = new Package(name, + System.getProperty(java.specification.name), + System.getProperty(java.specification.vendor), + System.getProperty(java.specification.version), + GNU Classpath, + GNU, + Configuration.CLASSPATH_VERSION, + null); + +synchronized (definedPackages) + { +definedPackages.put(name, p); + } + } +return p; } + /** - * Helper to get all packages from the bootstrap class loader. The default - * implementation of returning an empty array may be adequate, or you may - * decide that this needs some native help. + * Helper to get all packages from the bootstrap class loader. * * @return all named packages, if any exist */ static Package[] getPackages() { -return new Package[0]; +Package[] packages; +synchronized(definedPackages) + { +packages = new Package[definedPackages.size()]; +definedPackages.values().toArray(packages); + } +return packages; } /** Index: java/lang/Class.java === RCS file: /cvsroot/classpath/classpath/java/lang/Class.java,v retrieving revision 1.40 diff -u -r1.40 Class.java --- java/lang/Class.java15 Sep 2005 14:42:36 - 1.40 +++ java/lang/Class.java21 Oct 2005 21:06:12 - @@ -594,7 +594,8 @@ ClassLoader cl = getClassLoader(); if (cl != null) return cl.getPackage(getPackagePortion(getName())); -return null; +else + return VMClassLoader.getVMPackage(getPackagePortion(getName())); } /** ___ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches
Re: [cp-patches] RFC: implementation of getPackage for the vm reference
Hi Jeroen After looking at it some more, I think the patch is actually incorrect. There should be no need to introduce the new VMClassLoader.getVMPackage() method. VMClassLoader.getPackage() should actually be doing that work and Class.getPackage() should be calling VMClassLoader.getPackage if cl is null. That's what I thought too in the first place, but the ClassLoader.getPackage calls the parent loader's getPackage method. If the parent is null, then it calls VMClassLoader.getPackage(). If VMClassLoader.getPackage had to add the package given as parameter, then all packages (system + applications) would be defined in VMClassLoader.definedPackages. I hope I'm clear enough. The suggestion you gave for getPackages (having all bootstrap packages in VMClassLoader.definedPackages at startup) could remove the additional VMClassLoader.getVMPackage. Maybe that's a better solution? (Sun does it) Regards, Jeroen Nicolas ___ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches
Re: New GNU Classpath developers Nicolas and Christian
Hi Mark, hi all Thank you for your welcome messages. To say a little more about me, I'm the maintainer of a java virtual machine called JnJVM using gnu classpath as its core classes. The vm has originally been developped by Gael Thomas. You can get more informations on his home page http://www-src.lip6.fr/homepages/Gael.Thomas/ It's more a personal page, but i'm optimistic one day we'll have something more professional. Cheers, Nicolas Mark Wielaard wrote: Hi all, Now that we are growing so fast it is probably a good idea to introduce new developers officially on the list so everybody knows when the GNU Classpath family gains a new member. Everybody with CVS write access is of course also listed on our savannah page: https://savannah.gnu.org/project/memberlist.php?group=classpath Nicolas Geoffray has been helping us out with RMI, Serialization and Classloader issues. Christian (twisti) Thalinger has been helping and fixing issues so the Cacao plus GNU Classpath combination truly rocks (especially on non-x86 platforms). Note that you don't have to apply for CVS write access if you don't want to. If you just want to supply an occasional patch now and then and your paperwork is in order it can just as easily be applied by one of the regulars after you sent it to the classpath-patches list or added it to bugzilla. But it is often easier to be able to do it yourself. So don't hesitate to ask me to add you to the list. At the irc meeting at the start of this month we discussed whether more formal rules are needed. Everybody seemed to agree that if the legal side is correctly handled then we should not impose any extra procedures unless there is a clear need (people acting in some anti-social way). So the rules (1) are more like gentlemen agreements. We expect people to play nice, listen to each other and take each others opinion seriously. This seems to work just fine. And we hope to keep it that way. Please help out by reviewing patches of new members quickly with some extra care and love (nitpicking allowed if you do it gently). Happy Hacking, Mark (1) Our rules are outlined in the GNU Classpath Hacker Guide: http://www.gnu.org/software/classpath/docs/hacking.html Everybody should read them and where possible improve them! ___ Classpath mailing list Classpath@gnu.org http://lists.gnu.org/mailman/listinfo/classpath
Interruption of InterruptibleChannel methods
Hi all, Implementing the Thread.interrupt inside my vm, I noticed nothing is actually done inside classpath (except for native/jni/java-nio/gnu_java_nio_VMSelector.c) for dealing with interruption of a thread executing an InterruptibleChannel method. I tried to look what other VMs do, but i feel like the implementation never completely covers the issue (maybe I'm wrong? Jamvm says Full thread implementation including Thread.interrupt, but is the implementation of Thread.interrupt full?). I have the feeling that something has to be done inside ||gnu classpath in order for a a vm to correctly deal with the interruption of a thread inside an InterruptibleChannel method. Is this kind of discussion present elsewhere? I didn't find it in the archives. And the docs in gnu classpath and vms seem like forgiving the issue. Cheers, Nicolas|| || ___ Classpath mailing list Classpath@gnu.org http://lists.gnu.org/mailman/listinfo/classpath
[commit-cp] classpath/vm/reference/java/lang VMClassLoader....
CVSROOT:/cvsroot/classpath Module name:classpath Branch: Changes by: Nicolas Geoffray [EMAIL PROTECTED]05/10/21 10:47:17 Modified files: vm/reference/java/lang: VMClassLoader.java Log message: 2005-10-21 Nicolas Geoffray [EMAIL PROTECTED] * vm/reference/java/lang/VMClassLoader.java (getResources): uses a new static field HashMap to store opened zip files from property java.boot.class.path. CVSWeb URLs: http://savannah.gnu.org/cgi-bin/viewcvs/classpath/classpath/vm/reference/java/lang/VMClassLoader.java.diff?tr1=1.31tr2=1.32r1=textr2=text
[commit-cp] classpath/vm/reference/java/lang VMClassLoader....
CVSROOT:/cvsroot/classpath Module name:classpath Branch: Changes by: Nicolas Geoffray [EMAIL PROTECTED]05/10/21 10:25:14 Modified files: vm/reference/java/lang: VMClassLoader.java Log message: 2005-10-21 Nicolas Geoffray [EMAIL PROTECTED] * vm/reference/java/lang/VMClassLoader.java (getRessources): In case the property java.boot.class.path contains directories, tests if the ressource exists before adding it to the vector result. CVSWeb URLs: http://savannah.gnu.org/cgi-bin/viewcvs/classpath/classpath/vm/reference/java/lang/VMClassLoader.java.diff?tr1=1.30tr2=1.31r1=textr2=text
[commit-cp] classpath ChangeLog
CVSROOT:/cvsroot/classpath Module name:classpath Branch: Changes by: Nicolas Geoffray [EMAIL PROTECTED]05/10/21 19:18:50 Modified files: . : ChangeLog Log message: 2005-10-21 Nicolas Geoffray [EMAIL PROTECTED] * vm/reference/java/lang/VMClassLoader.java (getRessources): In case the property java.boot.class.path contains directories, tests if the ressource exists before adding it to the vector result. CVSWeb URLs: http://savannah.gnu.org/cgi-bin/viewcvs/classpath/classpath/ChangeLog.diff?tr1=1.5313tr2=1.5314r1=textr2=text
[commit-cp] classpath ChangeLog
CVSROOT:/cvsroot/classpath Module name:classpath Branch: Changes by: Nicolas Geoffray [EMAIL PROTECTED]05/10/21 19:20:49 Modified files: . : ChangeLog Log message: 2005-10-21 Nicolas Geoffray [EMAIL PROTECTED] * vm/reference/java/lang/VMClassLoader.java (getResources): uses a new static field HashMap to store opened zip files from property java.boot.class.path. CVSWeb URLs: http://savannah.gnu.org/cgi-bin/viewcvs/classpath/classpath/ChangeLog.diff?tr1=1.5314tr2=1.5315r1=textr2=text
[cp-patches] RFC: VMClassLoader : hashmap for jars from property java.boot.class.path
Hi, I improved the reference implementation of VMClassLoader.getRessources by adding a static HashMap which is filled when a boot zip is opened (typically glibj.zip). In the previous implementation, the code kept opening and closing the zip file. Another solution would be to have a static initializer for VMClassLoader which would parse the java.boot.class.path property, and puts the files into a static Enumeration object. I tried this solution too, but performance isn't improved and it results in all boot files opened. Comments welcomed 2005-10-06 Nicolas Geoffray [EMAIL PROTECTED] * vm/reference/java/lang/VMClassLoader.java (getResources): uses a new static field HashMap to store opened zip files from property java.boot.class.path. Cheers, Nicolas --- classpath-0.18/vm/reference/java/lang/VMClassLoader.java 2005-10-06 10:26:34.0 +0200 +++ classpath-0.18-jnjvm/vm/reference/java/lang/VMClassLoader.java 2005-10-06 14:47:02.0 +0200 @@ -119,6 +119,9 @@ return null; } + /** jars from property java.boot.class.path */ + static final HashMap bootjars = new HashMap(); + /** * Helper to get a list of resources from the bootstrap class loader. * @@ -139,8 +142,9 @@ { try { - v.add(new URL(file:// - + new File(file, name).getAbsolutePath())); +File f = new File(file, name); +if(!f.exists()) continue; +v.add(new URL(file:// + f.getAbsolutePath())); } catch (MalformedURLException e) { @@ -150,30 +154,28 @@ else if (file.isFile()) { ZipFile zip; - try - { - zip = new ZipFile(file); - } - catch (IOException e) - { - continue; - } - String zname = name.startsWith(/) ? name.substring(1) : name; - try - { - if (zip.getEntry(zname) == null) +synchronized(bootjars) + { +zip = (ZipFile) bootjars.get(file.getName()); + } +if(zip == null) + { +try + { +zip = new ZipFile(file); +synchronized(bootjars) + { +bootjars.put(file.getName(), zip); + } + } + catch (IOException e) + { continue; - } - finally - { - try - { - zip.close(); - } - catch (IOException e) - { - } - } + } + } + String zname = name.startsWith(/) ? name.substring(1) : name; + if (zip.getEntry(zname) == null) + continue; try { v.add(new URL(jar:file:// ___ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches
Wrong exception thrown in AccessContoller
Hello everyone, In java.security.AccessController doPrivileged(PrivilegedExceptionAction) and doPrivileged(PrivilegedExceptionAction, AccessControlContext) are supposed to wrap all checked exceptions thrown in a PrivilegedActionException object. By checked it means all exceptions but RuntimeException. The implementation of the two methods in gnu classpath treats non checked exceptions as checked exceptions, which is not a correct behaviour. I attached a patch (it's patched against 0.13, but it's ok for 0.18) and a java program which execution is different between sun and gnu classpath. Cheers, Nicolas import java.security.*; public class Access{ public static void main(String [] args){ try { String s = (String) AccessController.doPrivileged( new PrivilegedExceptionAction() { public Object run(){ Object o = null; return o.toString(); } }); } catch (PrivilegedActionException e) { System.out.println(e); } } } *** classpath-0.13/java/security/AccessController.java Fri Jan 7 00:32:28 2005 --- classpath-0.13-jnjvm/java/security/AccessController.java Mon Jun 20 14:56:44 2005 *** *** 153,158 --- 153,162 { return action.run(); } + catch (RuntimeException e) + { + throw e; + } catch (Exception e) { throw new PrivilegedActionException(e); *** *** 190,195 --- 194,203 { return action.run(); } + catch (RuntimeException e) + { + throw e; + } catch (Exception e) { throw new PrivilegedActionException(e); ___ Classpath mailing list Classpath@gnu.org http://lists.gnu.org/mailman/listinfo/classpath
Re: Loader in ObjectStreamClass.readClassDescriptor
Hi Mark, Mark Wielaard wrote: Hi Nicolas, On Tue, 2005-08-02 at 14:08 +0200, Nicolas Geoffray wrote: Hi everyone, sorry for the typo, it was ObjectInputStream.readClassDescriptor that misbehaves. Shortly, when a reading a given class descriptor CL, it loads the class of a field from CL with the currentClassLoader on the stack. But in RMI, the currentClassLoader is null, so loading the fields' classes won't work for classes that are not in the bootclasspath (glibj.zip). The algorithm with RMI will however succeed to load the class CL itself because it uses the method resolveClass from gnu.java.rmi.server.RMIObjectInputStream. The patch given fixes the problem by loading the fields' class of CL with CL's classloader. I agree it looks like we are doing something dodgy here. Using the class loader of the class itself to resolve the field classes seems better then using the current class loader if resolveClass() is overridden. Do you happen to have a little testcase for this? Either using rmi or some other class that overrides ObjectInputStream.resolveClass(). Then we can put that in Mauve. Three files for testing are attached. It's more an RMI related issue, since the thread class for rmi is gnu.java.rmi.server.UnicastConnection, which is loaded by the vm classloader. Consequence is that the current classloader in stack is null. ReceiveObjectImpl is the RMI object. Just rmic and launch it. Then launch Main. While we're at it, there might also be something to change in, this time, ObjectStreamClass.setClass. In the method it tries to compare the serial uids bewteen the local class and the stream class. It does it for all classes, even for array classes, which is wrong because array classes do not have serial uids. An array class does have a serial uid. But it is calculated slightly differently because we have to pretend an array class does not implement any interfaces. I thought arrays do not have uids because their implementation is native. How can you calculate an uid for a native type? I'm also interested to know how compatible are the algorithms between java and gnu classpath for computing the serial version uid? When I tried to communicate a sun vm with mine, it says that my HelloWorld class isn't compatible between the vms. Is that normal or are the algorithms compatibles and I did something wrong? The algorithms should be compatible. But since compilers can generate different class members (like synthetic methods or inner class names) a class compiled with different (versions of) compilers might not have the same serial version uid. See also: http://www.gnu.org/software/classpath/docs/hacking.html#SEC18 OK, thanks Cheers, Mark Cheers, Nicolas import java.rmi.Naming; public class Main{ class Foo implements java.io.Serializable{} class Bar implements java.io.Serializable{ Foo f = new Foo(); } public static void main(String[]args){ try{ Bar b = new Bar(); ReceiveObject ref = (ReceiveObject) Naming.lookup(rmi://localhost/ReceiveObject); ref.receiveObject(b); }catch(Exception e){ System.out.println(Error : + e ); } } } import java.rmi.Remote; import java.rmi.RemoteException; public interface ReceiveObject extends Remote{ public Object receiveObject(Object unknown) throws RemoteException; } import java.rmi.*; import java.rmi.server.*; public class ReceiveObjectImpl extends UnicastRemoteObject implements ReceiveObject{ public ReceiveObjectImpl() throws RemoteException{ } public Object receiveObject(Object unknown) throws RemoteException{ System.out.println(unknown); return null; } public static void main(String[] args){ try{ ReceiveObject ref = new ReceiveObjectImpl(); Naming.rebind(ReceiveObject, ref); }catch(Exception e){ e.printStackTrace(); } } } ___ Classpath mailing list Classpath@gnu.org http://lists.gnu.org/mailman/listinfo/classpath
Re: Loader in ObjectStreamClass.readClassDescriptor
Hi everyone, sorry for the typo, it was ObjectInputStream.readClassDescriptor that misbehaves. Shortly, when a reading a given class descriptor CL, it loads the class of a field from CL with the currentClassLoader on the stack. But in RMI, the currentClassLoader is null, so loading the fields' classes won't work for classes that are not in the bootclasspath (glibj.zip). The algorithm with RMI will however succeed to load the class CL itself because it uses the method resolveClass from gnu.java.rmi.server.RMIObjectInputStream. The patch given fixes the problem by loading the fields' class of CL with CL's classloader. While we're at it, there might also be something to change in, this time, ObjectStreamClass.setClass. In the method it tries to compare the serial uids bewteen the local class and the stream class. It does it for all classes, even for array classes, which is wrong because array classes do not have serial uids. I'm also interested to know how compatible are the algorithms between java and gnu classpath for computing the serial version uid? When I tried to communicate a sun vm with mine, it says that my HelloWorld class isn't compatible between the vms. Is that normal or are the algorithms compatibles and I did something wrong? Thanks all for your attention Cheers, Nicolas Nicolas Geoffray wrote: Hello again, There's something that, I think, misbehaves in readClassDescriptor. Fields are read before the loading of the actual object's class CL in the stream, which is necessary. When loading the classes of the fields (before loading CL), the classloader given is the callersClassLoader which is set to currentLoader() the most recent user defined classloader on the execution stack. When using the method with RMI here is the class context : class java.io.VMObjectInputStream$1 class java.security.AccessController class java.io.VMObjectInputStream class java.io.ObjectInputStream class java.io.ObjectInputStream class java.io.ObjectInputStream class java.io.ObjectInputStream class gnu.java.rmi.server.RMIObjectInputStream class gnu.java.rmi.server.UnicastServerRef class gnu.java.rmi.server.UnicastServer class gnu.java.rmi.server.UnicastServer class gnu.java.rmi.server.UnicastConnection class java.lang.Thread class java.lang.VMThread So the callersClassLoader is set to null and the fields of CL are loaded with the VM ClassLoader (which won't found any classes loaded by the application class loader or other user defined classloader) Because RMI redefines the resolveClass(ObjectStreamClass), CL is found, as it used the correct classloader. The problem arrives when CL was loaded by MyClassLoader, and CL has one field whose class was also loaded by MyClassLoader. What I suggest is to use the classloader of CL, once CL is loaded, to load the fields. What i do in the attached patch is reading the fields and storing them in a temporary class, loading CL as it was done before (this is when the RMI's resolveClass is used : gnu.java.rmi.server.RMIObjectInputStream) and finally loading the fields with CL's classloader. Would that be a correct behaviour? Cheers Nicolas *** java/io/ObjectInputStream.java Fri Jul 15 15:57:35 2005 --- java/io/ObjectInputStream.java Fri Jul 22 15:36:01 2005 *** *** 468,473 --- 468,484 } } + + private class TemporaryStreamField{ + String field_name; + String class_name; + + TemporaryStreamField(String field, String clazz){ + field_name = field; + class_name = clazz; + } + } + /** * This method reads a class descriptor from the real input stream * and use these data to create a new instance of ObjectStreamClass. *** *** 497,509 short field_count = this.realInputStream.readShort(); if(dump) dumpElementln(Short.toString(field_count)); ObjectStreamField[] fields = new ObjectStreamField[field_count]; ObjectStreamClass osc = new ObjectStreamClass(name, uid, flags, fields); assignNewHandle(osc); - if (callersClassLoader == null) - callersClassLoader = currentLoader(); - for (int i = 0; i field_count; i++) { if(dump) dumpElement( TYPE CODE=); --- 508,518 short field_count = this.realInputStream.readShort(); if(dump) dumpElementln(Short.toString(field_count)); ObjectStreamField[] fields = new ObjectStreamField[field_count]; + TemporaryStreamField[] temp_fields = new TemporaryStreamField[field_count]; ObjectStreamClass osc = new ObjectStreamClass(name, uid, flags, fields); assignNewHandle(osc); for (int i = 0; i field_count; i++) { if(dump) dumpElement( TYPE CODE=); *** *** 521,529 class_name = (String)readObject
Loader in ObjectStreamClass.readClassDescriptor
Hello again, There's something that, I think, misbehaves in readClassDescriptor. Fields are read before the loading of the actual object's class CL in the stream, which is necessary. When loading the classes of the fields (before loading CL), the classloader given is the callersClassLoader which is set to currentLoader() the most recent user defined classloader on the execution stack. When using the method with RMI here is the class context : class java.io.VMObjectInputStream$1 class java.security.AccessController class java.io.VMObjectInputStream class java.io.ObjectInputStream class java.io.ObjectInputStream class java.io.ObjectInputStream class java.io.ObjectInputStream class gnu.java.rmi.server.RMIObjectInputStream class gnu.java.rmi.server.UnicastServerRef class gnu.java.rmi.server.UnicastServer class gnu.java.rmi.server.UnicastServer class gnu.java.rmi.server.UnicastConnection class java.lang.Thread class java.lang.VMThread So the callersClassLoader is set to null and the fields of CL are loaded with the VM ClassLoader (which won't found any classes loaded by the application class loader or other user defined classloader) Because RMI redefines the resolveClass(ObjectStreamClass), CL is found, as it used the correct classloader. The problem arrives when CL was loaded by MyClassLoader, and CL has one field whose class was also loaded by MyClassLoader. What I suggest is to use the classloader of CL, once CL is loaded, to load the fields. What i do in the attached patch is reading the fields and storing them in a temporary class, loading CL as it was done before (this is when the RMI's resolveClass is used : gnu.java.rmi.server.RMIObjectInputStream) and finally loading the fields with CL's classloader. Would that be a correct behaviour? Cheers Nicolas *** java/io/ObjectInputStream.java Fri Jul 15 15:57:35 2005 --- java/io/ObjectInputStream.java Fri Jul 22 15:36:01 2005 *** *** 468,473 --- 468,484 } } + + private class TemporaryStreamField{ + String field_name; + String class_name; + + TemporaryStreamField(String field, String clazz){ + field_name = field; + class_name = clazz; + } + } + /** * This method reads a class descriptor from the real input stream * and use these data to create a new instance of ObjectStreamClass. *** *** 497,509 short field_count = this.realInputStream.readShort(); if(dump) dumpElementln(Short.toString(field_count)); ObjectStreamField[] fields = new ObjectStreamField[field_count]; ObjectStreamClass osc = new ObjectStreamClass(name, uid, flags, fields); assignNewHandle(osc); - if (callersClassLoader == null) - callersClassLoader = currentLoader(); - for (int i = 0; i field_count; i++) { if(dump) dumpElement( TYPE CODE=); --- 508,518 short field_count = this.realInputStream.readShort(); if(dump) dumpElementln(Short.toString(field_count)); ObjectStreamField[] fields = new ObjectStreamField[field_count]; + TemporaryStreamField[] temp_fields = new TemporaryStreamField[field_count]; ObjectStreamClass osc = new ObjectStreamClass(name, uid, flags, fields); assignNewHandle(osc); for (int i = 0; i field_count; i++) { if(dump) dumpElement( TYPE CODE=); *** *** 521,529 class_name = (String)readObject(); else class_name = String.valueOf(type_code); ! ! fields[i] = ! new ObjectStreamField(field_name, class_name, callersClassLoader); } /* Now that fields have been read we may resolve the class --- 530,537 class_name = (String)readObject(); else class_name = String.valueOf(type_code); ! ! temp_fields[i] = new TemporaryStreamField(field_name, class_name); } /* Now that fields have been read we may resolve the class *** *** 558,563 --- 566,577 throw cnfe; } + ClassLoader loader = clazz.getClassLoader(); + for(int i =0; i field_count; i++) + fields[i] = new ObjectStreamField(temp_fields[i].field_name, + temp_fields[i].class_name, loader); + + boolean oldmode = setBlockDataMode(true); osc.setClass(clazz, lookupClass(clazz.getSuperclass())); classLookupTable.put(clazz, osc); ___ Classpath mailing list Classpath@gnu.org http://lists.gnu.org/mailman/listinfo/classpath
hasClassInitializer and exception
Hey everyone, there is something that might be wrong in the implementation of VMObjectStreamClass.hasClassInitializer (native/jni/java-io/java_io_VMObjectStreamClass.c). It uses GetStaticMethodID and tests if an exception occured to see if the clinit method exists. The thing is, in the spec, GetStaticMethodID has to clinit the class. Imagine there is a clinit and the clinit raises and exception, the result of hasClassInitializer would be false. I have no patch to propose to you, but what i did (as a vm implementor) is reimplementing the VMObjectStreamClass.hasClassInitializer function, which now does the search without cliniting the class (so it doesn't use jni directly anymore). Am I right? Nicolas ___ Classpath mailing list Classpath@gnu.org http://lists.gnu.org/mailman/listinfo/classpath
Re: ResourceBundle optimisation
Hi Bryce, Bryce McKinlay wrote: Nicolas Geoffray wrote: My mistake, i gave you a patch against classpath-0.13. Here's a patch against the latest cvs. Nicolas Geoffray wrote: Hi everyone, I've been doing benchmarks beween my vm and another one launching Tomcat and noticed that the startup spent a long time trying to find Resouces with getBundle. The thing is, ResourceBundle uses a cache for the resources it founds, but i think it's not perfectly used. When getBundle is entered, it first tries to find the resource in the cache. If it's not found, it calls tryBundle. Then tryBundle tries to load ressources with different locales, but never searches in the cache, allthough it could. I made a patch for it and gained 2 minutes during startup of tomcat (using an ibook 500Mhz). It's attached. Hi Nicolas, I don't think this patch is correct. If an application requests the same bundle baseName, but with a different locale, the locale argument will be ignored and the first bundle placed in the cache will be returned. No, because in tryBundle, a new string is created with basename + locale. It is that new string that is put in the cache, not just the basename. For example, say you're looking for a resource MyResource with locale en_US. If it is found, then the result is cached with a key created from MyResource_en_US, not MyResource. Never the less, I'd be interested to know where the 2 minute speedup came from, and if there is anything we can do to improve ResourceBundle without breaking its semantics. Does Tomcat request the same bundle baseName for many different locales? It is when it loads struts. It is looking for a resource ApplicationProperties with all the locales classpath has. With the current implementation of ResourceBundle, looking for all resources takes a real long time. Here's an example : 1) You're in getBundle looking for resource ApplicationProperties with locale AA_aa 2) It's not in the cache, so you go into tryBundle 3) In tryBundle, you don't find ApplicationProperties_AA_aa 4) In tryBundle you find ApplicationProperties_AA so you return it 5) In getBundle you cache ApplicationProperties_AA_aa with the result (ApplicationProperties_AA is not cached) 6) In the next getBundle, you're looking for ApplicationProperties with locale AA... The patch improves the researches by caching ApplicationProperties_AA. Even better, in tryBundle when a result is found for a resource, we could cache all intermediary resources we were looking for. For example if we were looking for ApplicationProperties_AA_aa, and finally found a result for ApplicationProperties (with no locale), we could cache ApplicationProperties, ApplicationProperties_AA_aa, and ApplicationProperties_AA with that same result. I haven't done this greater optimisation, as i'm not sure of the correctness of the patch regarding the most specialized bundle in tryBundle. Regards Bryce Nicolas ___ Classpath mailing list Classpath@gnu.org http://lists.gnu.org/mailman/listinfo/classpath
ResourceBundle optimisation
Hi everyone, I've been doing benchmarks beween my vm and another one launching Tomcat and noticed that the startup spent a long time trying to find Resouces with getBundle. The thing is, ResourceBundle uses a cache for the resources it founds, but i think it's not perfectly used. When getBundle is entered, it first tries to find the resource in the cache. If it's not found, it calls tryBundle. Then tryBundle tries to load ressources with different locales, but never searches in the cache, allthough it could. I made a patch for it and gained 2 minutes during startup of tomcat (using an ibook 500Mhz). It's attached. Nicolas --- java/util/ResourceBundle.java 2005-01-07 00:32:28.0 +0100 +++ java/util/ResourceBundle.java 2005-06-29 17:19:43.101862656 +0200 @@ -287,23 +287,21 @@ private static class BundleKey { String baseName; -Locale locale; ClassLoader classLoader; int hashcode; BundleKey() {} -BundleKey(String s, Locale l, ClassLoader cl) +BundleKey(String s, ClassLoader cl) { - set(s, l, cl); + set(s, cl); } -void set(String s, Locale l, ClassLoader cl) +void set(String s, ClassLoader cl) { baseName = s; - locale = l; classLoader = cl; - hashcode = baseName.hashCode() ^ locale.hashCode() ^ + hashcode = baseName.hashCode() ^ classLoader.hashCode(); } @@ -319,7 +317,6 @@ BundleKey key = (BundleKey) o; return hashcode == key.hashcode baseName.equals(key.baseName) -locale.equals(key.locale) classLoader.equals(key.classLoader); } } @@ -419,22 +416,6 @@ lastDefaultLocale = defaultLocale; } -// This will throw NullPointerException if any arguments are null. -lookupKey.set(baseName, locale, classLoader); - -Object obj = bundleCache.get(lookupKey); -ResourceBundle rb = null; - -if (obj instanceof ResourceBundle) - { -return (ResourceBundle) obj; - } -else if (obj == nullEntry) - { -// Lookup has failed previously. Fall through. - } -else - { // First, look for a bundle for the specified locale. We don't want // the base bundle this time. boolean wantBase = locale.equals(defaultLocale); @@ -445,22 +426,10 @@ if (bundle == null !locale.equals(defaultLocale)) bundle = tryBundle(baseName, defaultLocale, classLoader, true); - BundleKey key = new BundleKey(baseName, locale, classLoader); -if (bundle == null) - { - // Cache the fact that this lookup has previously failed. - bundleCache.put(key, nullEntry); - } - else - { -// Cache the result and return it. - bundleCache.put(key, bundle); - return bundle; - } - } + if(bundle == null) +throw new MissingResourceException(Bundle + baseName + not found, baseName, ); -throw new MissingResourceException(Bundle + baseName + not found, - baseName, ); + return bundle; } /** @@ -527,9 +496,10 @@ is = ClassLoader.getSystemResourceAsStream(resourceName); else is = classloader.getResourceAsStream(resourceName); - if (is != null) +if (is != null){ bundle = new PropertyResourceBundle(is); } + } catch (IOException ex) { MissingResourceException mre = new MissingResourceException @@ -593,12 +563,32 @@ String bundleName = sb.toString(); ResourceBundle first = null; // The most specialized bundle. ResourceBundle last = null; // The least specialized bundle. - +ResourceBundle foundBundle = null; while (true) { -ResourceBundle foundBundle = tryBundle(bundleName, classLoader); + + lookupKey.set(bundleName, classLoader); + + Object obj = bundleCache.get(lookupKey); + + if (obj instanceof ResourceBundle) + { +foundBundle = (ResourceBundle) obj; + } + else if (obj == nullEntry) + { +foundBundle = null; + } + else{ +foundBundle = tryBundle(bundleName, classLoader); + } + + BundleKey key = new BundleKey(bundleName, classLoader); if (foundBundle != null) { + +bundleCache.put(key, foundBundle); + if (first == null) first = foundBundle; if (last != null) @@ -606,6 +596,10 @@ foundBundle.locale = locale; last = foundBundle; } + else +// Cache the fact that this lookup has previously failed. +bundleCache.put(key, nullEntry); + int idx = bundleName.lastIndexOf('_'); // Try the non-localized base name only if we already have a // localized child bundle, or wantBase is true. ___ Classpath mailing list Classpath@gnu.org http://lists.gnu.org/mailman/listinfo/classpath
Re: ResourceBundle optimisation
My mistake, i gave you a patch against classpath-0.13. Here's a patch against the latest cvs. Nicolas Geoffray wrote: Hi everyone, I've been doing benchmarks beween my vm and another one launching Tomcat and noticed that the startup spent a long time trying to find Resouces with getBundle. The thing is, ResourceBundle uses a cache for the resources it founds, but i think it's not perfectly used. When getBundle is entered, it first tries to find the resource in the cache. If it's not found, it calls tryBundle. Then tryBundle tries to load ressources with different locales, but never searches in the cache, allthough it could. I made a patch for it and gained 2 minutes during startup of tomcat (using an ibook 500Mhz). It's attached. Nicolas --- java/util/ResourceBundle.java 2005-07-06 21:51:21.243969910 +0200 +++ java/util/ResourceBundle.java 2005-07-06 21:53:14.870450642 +0200 @@ -247,24 +247,21 @@ private static class BundleKey { String baseName; -Locale locale; ClassLoader classLoader; int hashcode; BundleKey() {} -BundleKey(String s, Locale l, ClassLoader cl) +BundleKey(String s, ClassLoader cl) { - set(s, l, cl); + set(s, cl); } -void set(String s, Locale l, ClassLoader cl) +void set(String s, ClassLoader cl) { baseName = s; - locale = l; classLoader = cl; - hashcode = baseName.hashCode() ^ locale.hashCode() ^ -classLoader.hashCode(); + hashcode = baseName.hashCode() ^ classLoader.hashCode(); } public int hashCode() @@ -279,7 +276,6 @@ BundleKey key = (BundleKey) o; return hashcode == key.hashcode baseName.equals(key.baseName) -locale.equals(key.locale) classLoader.equals(key.classLoader); } } @@ -379,48 +375,20 @@ lastDefaultLocale = defaultLocale; } -// This will throw NullPointerException if any arguments are null. -lookupKey.set(baseName, locale, classLoader); - -Object obj = bundleCache.get(lookupKey); -ResourceBundle rb = null; - -if (obj instanceof ResourceBundle) - { -return (ResourceBundle) obj; - } -else if (obj == nullEntry) - { -// Lookup has failed previously. Fall through. - } -else - { - // First, look for a bundle for the specified locale. We don't want - // the base bundle this time. - boolean wantBase = locale.equals(defaultLocale); - ResourceBundle bundle = tryBundle(baseName, locale, classLoader, +// First, look for a bundle for the specified locale. We don't want +// the base bundle this time. +boolean wantBase = locale.equals(defaultLocale); +ResourceBundle bundle = tryBundle(baseName, locale, classLoader, wantBase); -// Try the default locale if neccessary. - if (bundle == null !locale.equals(defaultLocale)) - bundle = tryBundle(baseName, defaultLocale, classLoader, true); +// Try the default locale if neccessary. +if (bundle == null !locale.equals(defaultLocale)) + bundle = tryBundle(baseName, defaultLocale, classLoader, true); - BundleKey key = new BundleKey(baseName, locale, classLoader); -if (bundle == null) - { - // Cache the fact that this lookup has previously failed. - bundleCache.put(key, nullEntry); - } - else - { -// Cache the result and return it. - bundleCache.put(key, bundle); - return bundle; - } - } - -throw new MissingResourceException(Bundle + baseName + not found, +if (bundle == null) + throw new MissingResourceException(Bundle + baseName + not found, baseName, ); +return bundle; } /** @@ -553,12 +521,32 @@ String bundleName = sb.toString(); ResourceBundle first = null; // The most specialized bundle. ResourceBundle last = null; // The least specialized bundle. - +ResourceBundle foundBundle = null; while (true) { -ResourceBundle foundBundle = tryBundle(bundleName, classLoader); + + lookupKey.set(bundleName, classLoader); + + Object obj = bundleCache.get(lookupKey); + + if (obj instanceof ResourceBundle) + { +foundBundle = (ResourceBundle) obj; + } + else if (obj == nullEntry) + { +foundBundle = null; + } + else{ +foundBundle = tryBundle(bundleName, classLoader); + } + + BundleKey key = new BundleKey(bundleName, classLoader); if (foundBundle != null) { + +bundleCache.put(key, foundBundle); + if (first == null) first = foundBundle; if (last != null) @@ -566,6 +554,10 @@ foundBundle.locale = locale; last = foundBundle; } + else +// Cache the fact that this lookup has previously failed. +bundleCache.put(key, nullEntry); + int idx = bundleName.lastIndexOf('_'); // Try
Re: How to handle properties file
On Mon, 2005-05-23 at 10:31 +0200, Mark Wielaard wrote: Hi Nicolas, On Thu, 2005-05-19 at 23:24 +0200, Nicolas Geoffray wrote: If I'm asking, it's because i'm afraid as a vm implementor to make some code that will read a jar file (like glibj.zip) and do things like looking for *.properties files from it. I am afraid I have some bad news in that case. sorry. If you want to support our glibj.zip approach then you will need to provide that functionality. VMClassLoader (see vm/reference) depends on the runtime to provide a loadClass() method that reads the glibj.zip file to find the actual class (of provide the classes for the bootstrap classloader in some other way). There is also the VMClassLoader.getResource() and getResource() methods that finds bootstrap classloader resources. we currently provide a default implementation that uses java.util.zip for reading the glibj.zip file, but that is neither efficient (opens a new ZipFile each time) not completely safe (since reading zip files can trigger Date/Calendar calculations which need additional resources, which can get into endless recursion). Maybe we could actually provide the native glibj.zip file reading functionality completely in our vm reference code through zlib. That might not be such a bad idea since almost every runtime will need zlib to load the bootstrap classes and resources. The only trick is to make it flexible enough to be integrated into the various ways runtimes load classes. In fact, I already implemented the native glibj.zip file reading in my vm. It uses zlib but isn't usable for other vms (it's written with a dsl). What i was afraid of, is to take care of the .properties files (or whatever ressources apart form .class files) inside the glibj.zip file. Archie, I believe you said you had such code for JCVM and that you would consider donating that to GNU Classpath for use with other runtimes. If you have and want to could you send that code to the (patches) list? Do other runtime implementers think they would adopt such shared bootstrap class loading code, or is that something that is too wired into the actual runtime to be easy to share in a generic way? Good idea, might be interesting. Cheers, Mark -- Nicolas Geoffray [EMAIL PROTECTED] ___ Classpath mailing list Classpath@gnu.org http://lists.gnu.org/mailman/listinfo/classpath
How to handle properties file
Hello all, I'm a student in a french university and finalizing a jvm implementation, using the gnu classpath. I'm having a few questions (i hope it's the right place to ask). First question : how can i handle properties file stored in the glibj.zip. A simple example is the readConfiguration function in java/util/logging/LogManager class file. It first trys to get a java.util.logging.config.file property which should be a path in the filesystem. The thing is, it's in the glibj.zip file. There might be a hack somewhere in the FileInputStream to read from a zip file, but i'm not aware of it. Other question : shouldn't the function postInit from vm/reference/gnu/classpath/VMSystemProperties be native? It's my vm that reads the commande line that stands before the name of the class to execute. Thanks in advance for any replies -- Nicolas Geoffray [EMAIL PROTECTED] ___ Classpath mailing list Classpath@gnu.org http://lists.gnu.org/mailman/listinfo/classpath
Re: How to handle properties file
On Thu, 2005-05-19 at 16:27 +0200, Michael Koch wrote: On Thu, May 19, 2005 at 03:14:44PM +0200, Nicolas Geoffray wrote: Hello all, I'm a student in a french university and finalizing a jvm implementation, using the gnu classpath. I'm having a few questions (i hope it's the right place to ask). First question : how can i handle properties file stored in the glibj.zip. A simple example is the readConfiguration function in java/util/logging/LogManager class file. It first trys to get a java.util.logging.config.file property which should be a path in the filesystem. The thing is, it's in the glibj.zip file. There might be a hack somewhere in the FileInputStream to read from a zip file, but i'm not aware of it. Use java.lang.Class.getResourceAsStream(String) I didn't know that function. Powerfull! So then, shouldn't the function readConfiguration from LogManager make a call like LogManager.class.getResourceAsStream(java/util/logging/logging.properties); to have an InputStream instead of looking for system properties? Other question : shouldn't the function postInit from vm/reference/gnu/classpath/VMSystemProperties be native? It's my vm that reads the commande line that stands before the name of the class to execute. The VM* classes are special to the VM, they may be native but does not has to be. E.g. in JikesRVM and JNode nearly all stuff is implemented in Java itself. So it depends on your VM. OK Michael -- Nicolas Geoffray [EMAIL PROTECTED] ___ Classpath mailing list Classpath@gnu.org http://lists.gnu.org/mailman/listinfo/classpath
Re: How to handle properties file
On Thu, 2005-05-19 at 14:50 -0500, Archie Cobbs wrote: Michael Koch wrote: I didn't know that function. Powerfull! So then, shouldn't the function readConfiguration from LogManager make a call like LogManager.class.getResourceAsStream(java/util/logging/logging.properties); to have an InputStream instead of looking for system properties? Use java.util.Properties.load(InputStream) with it. Yes, this is what is done in the java.util.logging.LogManager.readconfiguration(InputStream). The thing is, i'm a vm implementor (not written in java) using the gnu classpath. So when a call to LogManager.readConfiguration is made in a java application, the ressource is not found. I can't use any of the functions you're pointing me, because i'm not the application, just the vm. I think people are missing Nicolas' point here. The class LogManager is broken, because it is looking in the wrong place for the properties file. Yes, that's it Archie. Does anyone know what the correct behavior is supposed to be? -Archie __ Archie Cobbs *CTO, Awarix* http://www.awarix.com ___ Classpath mailing list Classpath@gnu.org http://lists.gnu.org/mailman/listinfo/classpath
Re: How to handle properties file
On Fri, 2005-05-20 at 00:49 +0200, Robert Schuster wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Hi. I think people are missing Nicolas' point here. The class LogManager is broken, because it is looking in the wrong place for the properties file. Does anyone know what the correct behavior is supposed to be? A certain Jay-too-es-ee implementation loads it's logger configuration property file directly from the filesystem (at least it is stored there). I think this is what is intended to be emulated here. Due to certain packaging problems this would not work anyway on my distribution but this is a separate issue. A real problem is that our logging.properties file lives in java/util/logging inside the glibj.zip or more correctly: it is part of our system class path (remember that zipping the class library is an optional step) and the code is simply not correct. Maybe that is the reason for nicolas' initial problem. I file a bug for this. Thanks nicolas ;) OK, thx Robert for clearing up the situation, and for the bug report. cu Robert -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.1 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFCjRfvG9cfwmwwEtoRAirNAJ9Zq1uff4DgTvt+Izu042Pfkb5zIwCcCe0W i4FsnhCOWAMFCTu0stJHCGQ= =k4X7 -END PGP SIGNATURE- ___ Classpath mailing list Classpath@gnu.org http://lists.gnu.org/mailman/listinfo/classpath -- Nicolas Geoffray [EMAIL PROTECTED] ___ Classpath mailing list Classpath@gnu.org http://lists.gnu.org/mailman/listinfo/classpath
Re: How to handle properties file
On Fri, 2005-05-20 at 06:40 +0200, Michael Koch wrote: On Thu, May 19, 2005 at 11:24:16PM +0200, Nicolas Geoffray wrote: On Thu, 2005-05-19 at 21:54 +0200, Sascha Brawer wrote: Hi Nicolas, http://developer.classpath.org/doc/java/util/logging/LogManager.html I think the default config file should not be shipped as part of glibj.zip, but instead installed as a separate file. Sorry, I don't have the time right now to fix it myself... OK. Thank you Sascha for the answer. So, properties files inside a jar (or zip) archive are always handled by the application (or the gnu classpath files)? Nothing should be done at the opening of the jar file? If I'm asking, it's because i'm afraid as a vm implementor to make some code that will read a jar file (like glibj.zip) and do things like looking for *.properties files from it. Now I understand your original request. Sorry for my stupidity. No, not all *.properties files have to be outside of glibj.zip. E.g. we use property files to define locale data. These need to be still inside glibj.zip. Others should be outside to be editable by the administrator of the GNU classpath installation. Can you please file a No problem Michael, maybe i wasn't clear enough. So these property files inside the glibj.zip, who (the java application? gnu classpath? the vm?) handles it? bug report for this? Robert Schuster has. Thanks, Michael ___ Classpath mailing list Classpath@gnu.org http://lists.gnu.org/mailman/listinfo/classpath