glassfish4, ошибка загрузчика классов javacompiler при CompilationTask.метод вызова — не удается найти символ

#java #classloader #glassfish-4 #java-compiler-api

#java #загрузчик классов #glassfish-4 #java-compiler-api

Вопрос:

использование glassfish4, ошибки jdk1.7 в методе task.call(),

 >compiler.err.cant.resolve.location.args
>padm.exforms.MemoryFileManager$JavaSourceFromString[mfm:///CM.java]]]
>cannot find symbol
  symbol:   method getVal(int,int)
  location: class padm.exforms.CM]
and etc...
 

в клиенте j2se этот код работает нормально, на сервере glassfish возникают ошибки

пример кода;

 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector();
String className = "CM";

Class<?>_class = getClassFromString(compiler, diagnostics, Arrays.asList("-g:none", "-classpath", System.getProperty("java.class.path")), className, getClassCode(className));


  private Class<?> getClassFromString(JavaCompiler compiler, DiagnosticListener<JavaFileObject> listener, List<String> flags, String className, String classCode) {
    MemoryFileManager mfm = new MemoryFileManager(compiler.getStandardFileManager(listener, null, null));

    JavaFileObject fileObject = MemoryFileManager.makeSource(className, classCode);

    CompilationTask task = compiler.getTask(null, mfm, listener, flags, null, Arrays.asList(fileObject));
    if (task.call()) { //error in this call

      ClassLoader cl = mfm.getClassLoader(StandardLocation.CLASS_OUTPUT);

      try {
        return cl.loadClass(className);
      } catch (ClassNotFoundException e) {
        Logger.getLogger(getClass().getName()).log(Level.SEVERE, "err:"   e);
        return null;
      }
    } else
      return null;
  }


  private String getClassCode(String className) {
    StringBuilder sb = new StringBuilder();
    sb.append("package padm.exforms;"); //also tried without this line
    sb.append("import java.math.*; import java.sql.*; public class ");
    sb.append(className);
    sb.append(" extends ");
    sb.append(ConditionManager.class.getCanonicalName());
    sb.append("{public ");
    sb.append(className);
    sb.append("(){}");
}
 

как использовать javacompiler в glassfish4?
я также попытался установить делегат загрузчика классов =false в sun-web.xml , но после этого компоненты ejb не работают

Спасибо

Ответ №1:

Вы можете попробовать следующее:

Создайте новый ArrayList :

 List<JavaFileObject> classes = new ArrayList<JavaFileObject>();
 

Добавьте свой fileObject :

 classes.add(new SimpleJavaFileObject(new URI(PATH_TO_JAVA_FILE),JavaFileObject.Kind.SOURCE));
 

Передайте ArrayList getTask() методу:

 CompilationTask task = compiler.getTask(null, mfm, listener, flags, null, classes);
 

Другой способ:

 StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> classes = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(new File(PATH_TO_JAVA_FILE)));
CompilationTask task = compiler.getTask(null, mfm, listener, flags, null, classes);
 

Комментарии:

1. что должно быть установлено в PATH_TO_JAVA_FILE ? файл java является строкой

2. Как следует из названия переменной, путь к вашему java-файлу.

3. у меня нет файла java, исходный код java находится в объекте String, возврат из метода getClassCode()

Ответ №2:

чем это отличается от используемой версии? этот класс MemoryFileManager;

 import java.io.*;
import java.net.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.tools.*;
import javax.tools.JavaFileObject.Kind;

/**
 * A file manager for compiling strings to byte arrays. This file manager
 * delegates to another file manager to lookup classes on boot class path.
 * <p/>
 * <p>
 * <b>This is NOT part of any supported API. If you write code that depends on
 * this, you do so at your own risk. This code and its internal interfaces are
 * subject to change or deletion without notice.</b>
 * </p>
 *
 * @author Peter von der Ahamp;eacute;
 */
public final class MemoryFileManager extends ForwardingJavaFileManager<JavaFileManager> {
  /**
   * Maps binary class names to class files stored as byte arrays.
   */
  private Map<String, byte[]> classes;

  /**
   * Creates a JavaFileObject representing the given compilation unit.
   *
   * @param name a NAME representing this source code, for example, the NAME
   *             of a class
   * @param code a compilation unit (source code for a Java program)
   * @return a JavaFileObject represtenting the given compilation unit
   */
  public static JavaFileObject makeSource(String name, String code) {
    return new JavaSourceFromString(name, code);
  }

  /**
   * Construct a memory file manager which delegates to the specified file
   * manager for unknown sources.
   *
   * @param fileManager a file manager used to look up class files on class
   *                    path, etc.
   */
  public MemoryFileManager(JavaFileManager fileManager) {
    super(fileManager);
    classes = new HashMap();
  }

  /**
   * Get a class loader which first search the classes stored by this file
   * mananger.
   *
   * @return a class loader for compiled files
   */
  @Override
  public ClassLoader getClassLoader(Location location) {
    Enumeration<URL> e = null;
    try {
      e = MemoryFileManager.class.getClassLoader().getResources("");
    } catch (IOException e1) {
      Logger.getLogger(getClass().getName()).log(Level.SEVERE, "error:"   e1);
    }
    assert e != null;
    while (e.hasMoreElements()) {
      System.out.println("ClassLoader Resource: "   e.nextElement());
    }
    System.out.println("Class Resource: "   MemoryFileManager.class.getResource("/"));
    return new ByteArrayClassLoader(classes);
  }

  @Override
  public JavaFileObject getJavaFileForOutput(Location location, String name, Kind kind, FileObject originatingSource) throws UnsupportedOperationException {
    if (originatingSource instanceof JavaSourceFromString)
      return new JavaClassInArray(name);
    else
      throw new UnsupportedOperationException();
  }

  protected static URI uriFromString(String uri) {
    try {
      return new URI(uri);
    } catch (URISyntaxException e) {
      throw new IllegalArgumentException(e);
    }
  }

  /**
   * A file object representing a Java class file stored in a byte array.
   */
  private class JavaClassInArray extends SimpleJavaFileObject {

    private String name;

    /**
     * Constructs a JavaClassInArray object.
     *
     * @param name binary NAME of the class to be stored in this file object
     */
    JavaClassInArray(String name) {
      super(uriFromString("mfm:///"   name.replace('.', '/')   Kind.CLASS.extension), Kind.CLASS);
      this.name = name;
    }

    @Override
    public OutputStream openOutputStream() {
      return new FilterOutputStream(new ByteArrayOutputStream()) {
        @Override
        public void close() throws IOException {
          out.close();
          ByteArrayOutputStream bos = (ByteArrayOutputStream) out;
          classes.put(name, bos.toByteArray());
        }
      };
    }
  }

  /**
   * A file object used to represent source coming from a string.
   */
  private static class JavaSourceFromString extends SimpleJavaFileObject {
    /**
     * The source code of this "file".
     */
    final String code;

    /**
     * Constructs a new JavaSourceFromString.
     *
     * @param name the NAME of the compilation unit represented by this file
     *             object
     * @param code the source code for the compilation unit represented by
     *             this file object
     */
    JavaSourceFromString(String name, String code) {
      super(uriFromString("mfm:///"   name.replace('.', '/')   Kind.SOURCE.extension), Kind.SOURCE);
      this.code = code;
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) {
      return code;
    }
  }
}