代码之家  ›  专栏  ›  技术社区  ›  Josemy

是否可以缓存运行时编译的类?

  •  1
  • Josemy  · 技术社区  · 7 年前

    每当我试图缓存一个在运行时编译Java类的方法的结果时,第一次一切正常,但第二次(当从缓存中获得结果时)它会给我一个 ClassNotFoundException .我不知道这是不可能实现,还是我做错了什么。

    以下是我如何使用缓存调用该方法:

    public void execute() throws Exception {
        MyClass myclass = new MyClass();
        String code = "This is a really long JavaClass that implements CompiledClass"; // Retrieve JavaCode from somewhere
        for (int i = 0; i < 10; i++) {
                CompiledClass obj = myclass.getInstance("NameClassToCompile", code);
        }
    }
    

    这是方法可缓存的类:

    @Component
    @CacheConfig(cacheNames = "myCache")
    public class MyClass implements SomeClass {
    
        @Override
        @Cacheable(key = "#name")
        public CompiledClass getInstance(String name, String code) throws CustomException {
            try {
                // Save source in .java file.
                File root = Files.createTempDirectory(null).toFile();
                File sourceFile = new File(root, (this.getClass().getPackage().getName() + File.separator + name).replace('.', '/') + ".java");
                sourceFile.getParentFile().mkdirs();
                Files.write(sourceFile.toPath(), code.getBytes(StandardCharsets.UTF_8));
    
                // Compile source file.
                JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
                compiler.run(null, null, null, sourceFile.getPath());
    
                // Load and instantiate compiled class.
                Class<?> cls;
                try (URLClassLoader classLoader = URLClassLoader.newInstance(new URL[]{root.toURI().toURL()})) {
                    cls = Class.forName((this.getClass().getPackage().getName() + "." + name), true, classLoader);
                }
                return (CompiledClass) cls.getDeclaredConstructor().newInstance();
            } catch (InvocationTargetException | NoSuchMethodException | InstantiationException | IllegalAccessException | IOException | ClassNotFoundException e) {
                throw new CustomException("didn't work", e);
            }
        }
    

    我有一个例外:

    com.hazelcast.nio.serialization.HazelcastSerializationException: java.lang.ClassNotFoundException: com.mycompany.myartifact.mypackage.NameClassToCompile
    

    这就是我的Hazelcast配置:

    @Bean
    public Config hazelCastConfig() {
        return new Config()
            .setInstanceName("hazelcast")
            .addMapConfig(
                new MapConfig()
                    .setName("myCache")
                    .setMaxSizeConfig(new MaxSizeConfig(200, MaxSizeConfig.MaxSizePolicy.FREE_HEAP_SIZE))
                    .setEvictionPolicy(EvictionPolicy.LRU)
                    .setTimeToLiveSeconds(20));
    }
    

    这是实现所有编译类的接口。

    public interface CompiledClass extends Serializable {
    
        Long calculateSomething(String some);
    }
    

    以下是在运行时编译的代码示例:

    public class NameClassToCompile implements CompiledClass {
         @Override
         Long calculateSomething(String some) {
             return Long.valueOf(name.length());
         }
    }
    
    0 回复  |  直到 7 年前