diff --git a/jvm-cache/README.md b/jvm-cache/README.md
new file mode 100644
index 000000000..5f5b76054
--- /dev/null
+++ b/jvm-cache/README.md
@@ -0,0 +1 @@
+[jvm.pdf](doc%2Fjvm.pdf)
\ No newline at end of file
diff --git a/jvm-cache/doc/jvm.pdf b/jvm-cache/doc/jvm.pdf
new file mode 100644
index 000000000..7eb6643ce
Binary files /dev/null and b/jvm-cache/doc/jvm.pdf differ
diff --git a/jvm-cache/jar/nasl-metadata-collector-0.8.0.jar b/jvm-cache/jar/nasl-metadata-collector-0.8.0.jar
new file mode 100644
index 000000000..fffde156d
Binary files /dev/null and b/jvm-cache/jar/nasl-metadata-collector-0.8.0.jar differ
diff --git a/jvm-cache/jar/nasl-metadata-maven-plugin-1.3.0/install.bat b/jvm-cache/jar/nasl-metadata-maven-plugin-1.3.0/install.bat
new file mode 100644
index 000000000..a01a75d94
--- /dev/null
+++ b/jvm-cache/jar/nasl-metadata-maven-plugin-1.3.0/install.bat
@@ -0,0 +1 @@
+mvn install:install-file -Dfile="nasl-metadata-maven-plugin-1.3.0.jar" -DpomFile="pom.xml"
\ No newline at end of file
diff --git a/jvm-cache/jar/nasl-metadata-maven-plugin-1.3.0/install.sh b/jvm-cache/jar/nasl-metadata-maven-plugin-1.3.0/install.sh
new file mode 100644
index 000000000..a01a75d94
--- /dev/null
+++ b/jvm-cache/jar/nasl-metadata-maven-plugin-1.3.0/install.sh
@@ -0,0 +1 @@
+mvn install:install-file -Dfile="nasl-metadata-maven-plugin-1.3.0.jar" -DpomFile="pom.xml"
\ No newline at end of file
diff --git a/jvm-cache/jar/nasl-metadata-maven-plugin-1.3.0/nasl-metadata-maven-plugin-1.3.0.jar b/jvm-cache/jar/nasl-metadata-maven-plugin-1.3.0/nasl-metadata-maven-plugin-1.3.0.jar
new file mode 100644
index 000000000..0eaf1ec67
Binary files /dev/null and b/jvm-cache/jar/nasl-metadata-maven-plugin-1.3.0/nasl-metadata-maven-plugin-1.3.0.jar differ
diff --git a/jvm-cache/jar/nasl-metadata-maven-plugin-1.3.0/pom.xml b/jvm-cache/jar/nasl-metadata-maven-plugin-1.3.0/pom.xml
new file mode 100644
index 000000000..642d8f6b1
--- /dev/null
+++ b/jvm-cache/jar/nasl-metadata-maven-plugin-1.3.0/pom.xml
@@ -0,0 +1,74 @@
+
+ 4.0.0
+
+ com.netease.lowcode
+ nasl-metadata-maven-plugin
+ 1.3.0
+ maven-plugin
+
+ Nasl Metadata Maven Plugin
+
+ UTF-8
+
+
+
+
+ org.apache.maven
+ maven-plugin-api
+ 2.0
+
+
+ org.apache.maven
+ maven-project
+ 2.0.10
+
+
+ org.apache.maven.plugin-tools
+ maven-plugin-annotations
+ 3.2
+ provided
+
+
+ org.codehaus.plexus
+ plexus-compiler-manager
+ 2.8.4
+
+
+ org.codehaus.plexus
+ plexus-utils
+ 3.0.8
+
+
+ org.apache.maven.shared
+ maven-common-artifact-filters
+ 3.0.1
+
+
+
+ org.apache.maven
+ maven-aether-provider
+ 3.3.9
+
+
+
+ org.eclipse.aether
+ aether-api
+ 1.1.0
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-plugin-plugin
+ 3.2
+
+ nasl-metadata-maven-plugin
+ true
+
+
+
+
+
diff --git "a/jvm-cache/jvm\347\274\223\345\255\230.docx" "b/jvm-cache/jvm\347\274\223\345\255\230.docx"
new file mode 100644
index 000000000..056eca640
Binary files /dev/null and "b/jvm-cache/jvm\347\274\223\345\255\230.docx" differ
diff --git a/jvm-cache/pom.xml b/jvm-cache/pom.xml
new file mode 100644
index 000000000..3a0d728d2
--- /dev/null
+++ b/jvm-cache/pom.xml
@@ -0,0 +1,78 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.9.RELEASE
+
+
+
+ com.netease.cache
+ jvm-cache
+ 1.0.2
+
+
+ 8
+ 8
+ UTF-8
+ 3.3
+
+
+
+
+ nasl-metadata-collector
+ com.netease.lowcode
+ 0.8.0
+ true
+ system
+ ${project.basedir}/jar/nasl-metadata-collector-0.8.0.jar
+
+
+ com.google.guava
+ guava
+ 32.0.1-jre
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson.version}
+
+
+ org.slf4j
+ slf4j-api
+ provided
+ 1.7.30
+
+
+ org.springframework
+ spring-context
+ 5.2.8.RELEASE
+ provided
+
+
+
+
+
+ com.netease.lowcode
+ nasl-metadata-maven-plugin
+ 1.3.0
+
+ false
+
+
+
+
+ archive
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jvm-cache/src/main/java/com/netease/cache/jvm/api/FlexibleExpirationCache.java b/jvm-cache/src/main/java/com/netease/cache/jvm/api/FlexibleExpirationCache.java
new file mode 100644
index 000000000..fca879c95
--- /dev/null
+++ b/jvm-cache/src/main/java/com/netease/cache/jvm/api/FlexibleExpirationCache.java
@@ -0,0 +1,68 @@
+package com.netease.cache.jvm.api;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+public class FlexibleExpirationCache {
+ private final Cache cache;
+ private final ConcurrentHashMap expirationMap = new ConcurrentHashMap<>();
+
+ public FlexibleExpirationCache(Long maxSize) {
+ this.cache = CacheBuilder.newBuilder()
+ .removalListener(notification -> {
+ if (notification.getKey() != null) {
+ expirationMap.remove(notification.getKey());
+ }
+ })
+ .maximumSize(maxSize)
+ .build();
+ }
+
+ public void put(K key, V value, Long expireAfterWriteSeconds) {
+ cache.put(key, value);
+ expirationMap.put(key, System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(expireAfterWriteSeconds));
+ }
+
+ public V get(K key) {
+ if (isExpired(key)) {
+ invalidate(key);
+ return null;
+ }
+ return cache.getIfPresent(key);
+ }
+
+ public List getAllKeys() {
+ return new ArrayList<>(cache.asMap().keySet());
+ }
+
+ public V getValue(K key, Callable loader) {
+ try {
+ return cache.get(key, loader);
+ } catch (ExecutionException e) {
+ // 处理加载异常
+ throw new RuntimeException(e.getCause());
+ }
+ }
+
+ public boolean isExpired(K key) {
+ Long expiryTime = expirationMap.get(key);
+ return expiryTime != null && System.currentTimeMillis() > expiryTime;
+ }
+
+ public void invalidate(K key) {
+ cache.invalidate(key);
+ expirationMap.remove(key);
+ }
+
+ public void invalidateAll() {
+ cache.invalidateAll();
+ expirationMap.clear();
+ }
+}
diff --git a/jvm-cache/src/main/java/com/netease/cache/jvm/api/JvmCacheSpringEnvironmentConfiguration.java b/jvm-cache/src/main/java/com/netease/cache/jvm/api/JvmCacheSpringEnvironmentConfiguration.java
new file mode 100644
index 000000000..470e3016d
--- /dev/null
+++ b/jvm-cache/src/main/java/com/netease/cache/jvm/api/JvmCacheSpringEnvironmentConfiguration.java
@@ -0,0 +1,13 @@
+package com.netease.cache.jvm.api;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+
+/**
+ * @author system
+ */
+@Configuration
+@ComponentScan(basePackageClasses = LibraryAutoScan.class)
+public class JvmCacheSpringEnvironmentConfiguration {
+}
diff --git a/jvm-cache/src/main/java/com/netease/cache/jvm/api/JvmCacheUtil.java b/jvm-cache/src/main/java/com/netease/cache/jvm/api/JvmCacheUtil.java
new file mode 100644
index 000000000..1a8abc29e
--- /dev/null
+++ b/jvm-cache/src/main/java/com/netease/cache/jvm/api/JvmCacheUtil.java
@@ -0,0 +1,130 @@
+package com.netease.cache.jvm.api;
+
+import com.netease.lowcode.core.EnvironmentType;
+import com.netease.lowcode.core.annotation.Environment;
+import com.netease.lowcode.core.annotation.NaslConfiguration;
+import com.netease.lowcode.core.annotation.NaslLogic;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.util.List;
+import java.util.function.Function;
+
+@Component
+public class JvmCacheUtil {
+
+ private static FlexibleExpirationCache cache;
+
+ /**
+ * 缓存空间大小
+ * 类型为Long
+ */
+ @Value("${cacheMaximumSize}")
+ @NaslConfiguration(defaultValue = {@Environment(type = EnvironmentType.DEV, value = "100"),
+ @Environment(type = EnvironmentType.ONLINE, value = "100")})
+ public Long cacheMaximumSize;
+
+
+ @PostConstruct
+ public void init() {
+ cache = new FlexibleExpirationCache<>(cacheMaximumSize);
+ }
+
+ /**
+ * 添加缓存
+ *
+ * @param key 键
+ * @param value 值
+ * @param expireAfterWriteSeconds 过期时间(秒)
+ */
+ @NaslLogic
+ public String setCache(String key, String value, Long expireAfterWriteSeconds) {
+ assertNotNull(key, value, expireAfterWriteSeconds);
+ cache.put(key, value, expireAfterWriteSeconds);
+ return value;
+ }
+
+ /**
+ * 获取缓存
+ *
+ * @param key 键
+ * @return 值
+ */
+ @NaslLogic
+ public String getCache(String key) {
+ assertNotNull(key);
+ return cache.get(key);
+ }
+
+ /**
+ * 获取缓存,缓存不存在则执行function, 并将查询的值放到缓存中
+ */
+ @NaslLogic
+ public String getOrComputeAndSet(String key, Long expireAfterWriteSeconds, Function functionStr) {
+ assertNotNull(key, expireAfterWriteSeconds, functionStr);
+ String value = getCache(key);
+ if (value != null) {
+ return value;
+ }
+
+ String str = functionStr.apply(null);
+ if (str != null) {
+ setCache(key, str, expireAfterWriteSeconds);
+ }
+ return str;
+ }
+
+ /**
+ * 是否过期
+ *
+ * @param key 键
+ * @return true/false
+ */
+ @NaslLogic
+ public Boolean isExpired(String key) {
+ assertNotNull(key);
+ return cache.isExpired(key);
+ }
+
+ /**
+ * 清除缓存
+ *
+ * @param key 键
+ */
+ @NaslLogic
+ public Boolean invalidate(String key) {
+ assertNotNull(key);
+ cache.invalidate(key);
+ return true;
+ }
+
+ /**
+ * 清除所有缓存
+ */
+ @NaslLogic
+ public Boolean invalidateAll() {
+ cache.invalidateAll();
+ return true;
+ }
+
+ /**
+ * 查询缓存中所有的key
+ */
+ @NaslLogic
+ public List keys() {
+ return cache.getAllKeys();
+ }
+
+ private void assertNotNull(Object object) {
+ if (null == object) {
+ throw new RuntimeException("INPUT_INVALID");
+ }
+ }
+
+ private void assertNotNull(Object... objects){
+ for (Object object : objects) {
+ assertNotNull(object);
+ }
+ }
+}
diff --git a/jvm-cache/src/main/java/com/netease/cache/jvm/api/LibraryAutoScan.java b/jvm-cache/src/main/java/com/netease/cache/jvm/api/LibraryAutoScan.java
new file mode 100644
index 000000000..a9927cc45
--- /dev/null
+++ b/jvm-cache/src/main/java/com/netease/cache/jvm/api/LibraryAutoScan.java
@@ -0,0 +1,8 @@
+package com.netease.cache.jvm.api;
+
+/**
+ * 依赖库自动扫描类
+ * @author system
+ */
+public class LibraryAutoScan {
+}
diff --git a/jvm-cache/src/main/resource/META-INF/spring.factories b/jvm-cache/src/main/resource/META-INF/spring.factories
new file mode 100644
index 000000000..7fcd2c9c2
--- /dev/null
+++ b/jvm-cache/src/main/resource/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+com.netease.cache.jvm.api.JvmCacheSpringEnvironmentConfiguration
\ No newline at end of file