Two questions regarding implementing ModuleFinder

Andrew Dinn adinn at redhat.com
Thu Jul 28 15:59:27 UTC 2016


Hi all,

In order to create a module for my agent at runtime I had to provide my
own implementations of classes ModuleFinder and ModuleReader. These
implementations delegate to the agent in order to retrieve bytecode for
a given class contained in the module so they do not themselves rely on
a file located on disk or on the network to provide this bytecode.

The implementations I came up with both appear to work but I am not
really sure why I needed to implement them the way I have. Perhaps
someone might be able to answer two questions I have, one for each
implementation:

1) My ModuleFinder class, JigsawModuleFinder, has to implement method
find(String), returning a ModuleReference for a given module name and
findall() return a Set<ModuleReferences>. I implemented the API as follows

public class JigsawModuleFinder implements ModuleFinder
  . . .
  public Optional<ModuleReference> find(String name)
  {
    if (moduleName.equals(name)) {
      return Optional.of(getModuleReference());
    };

    return null;
  }
  public Set<ModuleReference> findAll()
  {
    return Set.of(getModuleReference());
  }
  . . .

n.b. in the first implementation moduleName is a String instance field
naming the single module that my Finder is meant to find.

The (sole) module reference returned by these two methods is created by
method getModuleReference as follows

  private ModuleReference getModuleReference()
  {
    URI uri = null;
    try {
      uri = new URI("byteman", moduleName, null);
    } catch (URISyntaxException e) {
    }
    ModuleDescriptor desc = new ModuleDescriptor.Builder(moduleName).
        requires("java.instrument").
        exports(packageName).
        build();
    final ModuleReader reader = new JigsawModuleReader(classMapper);
    ModuleReference reference =
      new ModuleReference(desc, uri, new Supplier<ModuleReader>() {
        @Override
        public ModuleReader get()
        {
          return reader;
        }
      });

    return reference;
  }

n.b. classMapper is another instance field which identifies a
Map<String, byte[]> supplied by my agent. It's get method maps class
names to the corresponding class format byte[].

The part I am dubious about here is the URI, in particular the need to
provide a scheme (supplied as the String "byteman"). I passed that
because I get an error if I simply pass null for the scheme (it
complains that this is not an absolute URI). I can see that the module
should have a name but why does it need to be absolute? Indeed, why is
it needed at all? The various javadocs eventually lead to a suggestion
that the URI may be used by a security manager. If this is really what
it is for then do I need to worry about having invented scheme 'byteman'
out of thin air? WIl the security code ever try to convert it to a URL?

2) A related conundrum arises with my class Modulereader class,
JigsawModuleReader. It implements the public API as follows

public class JigsawModuleReader implements ModuleReader
{
  . . .
    public Optional<URI> find(String name) throws IOException
    {
        return Optional.empty();
    }

    public Optional<ByteBuffer> read(String name) throws IOException
    {
        byte[] classBytes = classMapper.get(name);
        if (classBytes != null) {
            ByteBuffer byteBuffer = ByteBuffer.wrap(classBytes) ;
            return Optional.of(byteBuffer);
        }
        return Optional.empty();
    }
    public void close() throws IOException
    {
        // nothing to do
    }
}

I am required to implement find as it has no default. I also need to
implement read so I can redirect to the agent to provide the class
format byte[]. However, it appears that find is only needed so it can be
called from the default method open and that open is only there to be
called from the default method read. Is there any possibility that
something else might call find?

Thanks for any help that anyone on the list can provide.

regards,


Andrew Dinn
-----------
Senior Principal Software Engineer
Red Hat UK Ltd
Registered in England and Wales under Company Registration No. 03798903
Directors: Michael Cunningham, Michael ("Mike") O'Neill, Eric Shander


More information about the jigsaw-dev mailing list