









Oracle java 扩展在Java项目上的支持度不如Redhat或微软的 Java 扩展,智能提示太慢并且代码重构功能很少,但它提供了一个基于java语言原生的notebook环境, 相较于基于Juypter的方案, 有着更快的运行速度, 基于JShell代码补全不是很好,仅能提示出method名, 不能显示完整的参数清单, 另外无法类似实现 inline matplotlib 功能,所以生成的plot显示不是很方便。
虽然 vscode oracle-java 内置了一个 maven 程序, 但检查maven项目的类库依赖不是很方便, 可以安装 Maven for java 插件,该插件会提供一个Maven管理面板,使用起来很方便。
notebook的功能还比较弱,比如代码提示仅仅显示method名,无法给出参数清单,无法类似实现 inline matplotlib 功能, 这些并不致命。
该插件的最大的问题是,当引入的jar太多时候, 会导致启动java命令行报命令行太长错误, 这个问题会直接影响maven项目的运行和调试, 也会影响notebook cell的运行。 根因在于-classpath 参数太长超过windows命令行8K的限制。
经过很多次的探索,包括但不限于:(1)vscode 缺省 terminal 设置为 powershell ;(2)launch.json 强制使用 @argument file,(3)launch.json 强制使用 powershell 命令。 这些方式都不管用。
但我最终还是将这个问题解决了。 方案如下:
增加了3个编译插件,完美地解决了该问题。
exec-maven-plugin 插件, 该插件启用了 longClasspath。 即使不安装该插件, Oracle java插件运行程序, 也是通过 exec-maven-plugin 启动程序的,我显式地启用了 longClasspath 后,运行程序将使用 Argument File 而不是 -classpath 参数,这样避免了命令行超长问题。spring-boot-maven-plugin 插件, 程序符合springboot项目规范, 通过该插件打包为fat jar,这样就可以实现单jar部署,也规避了命令行超长问题。jdk.notebook.classpath 参数才行, 需要将依赖的jar连同应用程序的class输出目录 target/classes 也一并加进去,jdk.notebook.classpath 或 pom.xml 变更后, 最好使用vscode命令 reload window重新加载notebook文件,然后再使用import语句。关键是jdk.notebook.classpath 参数,需要将依赖的jar连同应用程序的class输出目录 target/classes 也一并加进去,我将本地 maven 缓存的所有jar文件集中存在一个 all_jars 目录中,注意该参数不支持通配符,所以需要将每一个jar都配置进去,另外同一个jar如果有不同版本,只能加一个,否则有可能会导致版本冲突。
"jdk.telemetry.enabled": false,
"jdk.jdkhome": "D:\\my_program\\java\\jdk-26.0.1",
"jdk.notebook.classpath": [
"C:\\Users\\dorothy\\CodeBuddy\\20260319064631\\.codebuddy\\skills\\maven_project\\target\\classes",
"D:\\maven_packages\\all_jars\\tribuo-core-4.3.2.jar",
"D:\\maven_packages\\all_jars\\tribuo-data-4.3.2.jar",
"D:\\maven_packages\\all_jars\\tribuo-interop-core-4.3.2.jar",
],
"maven.executable.path": "C:\\Users\\dorothy\\.vscode\\extensions\\oracle.oracle-java-25.1.0\\nbcode\\java\\maven\\bin\\mvn.cmd",
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "jdk", //Oracle java插件需要取值为 jdk
"request": "launch",
"console": "internalConsole",
"name": "Launch Java App (oracle java) ",
"mainClass": "org.yourcompany.yourproject.DemoApplication",
"cwd": "${workspaceFolder}"
}
]
}
int hello=10;
System.out.println(hello);
String hello="a";
System.out.println(hello);
System.out.print("hello world");
import cn.hutool.core.util.StrUtil;
String hello=StrUtil.upperFirst("hello world");
System.out.print(hello);
说明: duckdb/tablesaw/DFLib都可访问csv等外部数据源, duckdb可使用sql进行数据处理, tablesaw/DFLib可使用data frame的方式进行数据处理, 另外tablesaw/DFLib都可通过jdbc访问db, 所以可以结合sql和dataframe两者的优势进行数据处理.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.yourcompany.yourproject</groupId>
<artifactId>DemoApplication</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>26</maven.compiler.release>
<exec.mainClass>org.yourcompany.yourproject.DemoApplication</exec.mainClass>
<exec.maven.version>3.6.3</exec.maven.version>
<hutool.version>5.8.44</hutool.version>
<duckdb.version>1.5.2.0</duckdb.version>
<pebble.version>3.1.5</pebble.version>
<tablesaw.version>0.42.0</tablesaw.version>
<tablesaw-parquet.version>0.10.0</tablesaw-parquet.version>
<dflib.version>1.3.0</dflib.version>
<jmetal.version>6.2</jmetal.version>
<tribuo.version>4.3.2</tribuo.version>
<smile.version>3.1.1</smile.version>
<weka.version>3.8.6</weka.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.0.6</version>
</parent>
<dependencies>
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>${exec.maven.version}</version>
</dependency>
<!-- spring-boot 核心启动器:包含自动配置、日志、YAML解析等基础功能 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- spring-boot- 单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- hutool -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<!-- duck db-->
<dependency>
<groupId>org.duckdb</groupId>
<artifactId>duckdb_jdbc</artifactId>
<version>${duckdb.version}</version>
</dependency>
<!-- Tablesaw need newer pebble version to support Java 17 -->
<dependency>
<groupId>io.pebbletemplates</groupId>
<artifactId>pebble</artifactId>
<version>${pebble.version}</version>
</dependency>
<!-- Core Tablesaw for data manipulation -->
<dependency>
<groupId>tech.tablesaw</groupId>
<artifactId>tablesaw-core</artifactId>
<version>${tablesaw.version}</version>
</dependency>
<!-- Tablesaw Plotly for charting/visualization -->
<dependency>
<groupId>tech.tablesaw</groupId>
<artifactId>tablesaw-jsplot</artifactId>
<version>${tablesaw.version}</version>
</dependency>
<dependency>
<groupId>tech.tablesaw</groupId>
<artifactId>tablesaw-json</artifactId>
<version>${tablesaw.version}</version>
</dependency>
<dependency>
<groupId>tech.tablesaw</groupId>
<artifactId>tablesaw-excel</artifactId>
<version>${tablesaw.version}</version>
</dependency>
<dependency>
<groupId>net.tlabs-data</groupId>
<artifactId>tablesaw_${tablesaw.version}-parquet</artifactId>
<version>${tablesaw-parquet.version}</version>
</dependency>
<dependency>
<groupId>org.dflib</groupId>
<artifactId>dflib</artifactId>
</dependency>
<dependency>
<groupId>org.dflib</groupId>
<artifactId>dflib-parquet</artifactId>
</dependency>
<dependency>
<groupId>org.dflib</groupId>
<artifactId>dflib-avro</artifactId>
</dependency>
<dependency>
<groupId>org.dflib</groupId>
<artifactId>dflib-echarts</artifactId>
</dependency>
<dependency>
<groupId>org.dflib</groupId>
<artifactId>dflib-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.dflib</groupId>
<artifactId>dflib-csv</artifactId>
</dependency>
<dependency>
<groupId>org.dflib</groupId>
<artifactId>dflib-excel</artifactId>
</dependency>
<dependency>
<groupId>org.dflib</groupId>
<artifactId>dflib-json</artifactId>
</dependency>
<dependency>
<groupId>org.uma.jmetal</groupId>
<artifactId>jmetal-core</artifactId>
<version>${jmetal.version}</version>
</dependency>
<dependency>
<groupId>org.uma.jmetal</groupId>
<artifactId>jmetal-algorithm</artifactId>
<version>${jmetal.version}</version>
</dependency>
<dependency>
<groupId>org.uma.jmetal</groupId>
<artifactId>jmetal-problem</artifactId>
<version>${jmetal.version}</version>
</dependency>
<dependency>
<groupId>com.github.haifengl</groupId>
<artifactId>smile-core</artifactId>
<version>${smile.version}</version>
</dependency>
<dependency>
<groupId>org.tribuo</groupId>
<artifactId>tribuo-all</artifactId>
<version>${tribuo.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>nz.ac.waikato.cms.weka</groupId>
<artifactId>weka-stable</artifactId>
<version>${weka.version}</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.dflib</groupId>
<artifactId>dflib-bom</artifactId>
<version>${dflib.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<!-- Oracle java 插件执行/调试都是使用 exec-maven-plugin 启动的进程的,这里设置 longClasspath 为 true,即告知
exec-maven-plugin 优化 classpath 参数以免超过Windows命令行8K长度限制 -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.6.3</version>
<configuration>
<mainClass>${exec.mainClass}</mainClass>
<!-- 关键配置: longClasspath -->
<longClasspath>true</longClasspath>
<useArgumentFile>true</useArgumentFile>
<classpathScope>runtime</classpathScope>
</configuration>
</plugin>
<plugin>
<!-- 使用 org.springframework.boot 插件完成fat jar包的打包, 这样使用单jar即可部署 -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- 主类(通常自动检测,无需配置) -->
<mainClass>${exec.mainClass}</mainClass>
<!-- 排除 DevTools 打包 -->
<excludeDevtools>true</excludeDevtools>
<!-- 分层打包(Docker 优化) -->
<layers>
<enabled>true</enabled>
</layers>
</configuration>
<executions>
<execution>
<goals>
<!-- 重新打包为可执行 JAR -->
<goal>repackage</goal>
<!-- 生成构建信息 -->
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<!-- 使用 maven-dependency-plugin 插件输出项目所有的依赖,方便将这些依赖文件集中到一起,并方便
settings.json中的 jdk.notebook.classpath 设置 -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.6.1</version>
<executions>
<!-- 定义一个 execution,绑定到 package 阶段 -->
<execution>
<!-- execution 的唯一标识 -->
<id>generate-classpath</id>
<!-- 绑定到 package 生命周期阶段 -->
<phase>package</phase>
<!-- 执行的目标(goal) -->
<goals>
<goal>build-classpath</goal>
</goals>
<!-- 该 execution 的配置 -->
<configuration>
<!-- classpath 输出文件路径 -->
<outputFile>${project.build.directory}/classpath.txt</outputFile>
<!-- 路径分隔符(显式指定,避免跨平台问题) -->
<pathSeparator>;</pathSeparator>
<!-- 文件路径分隔符 -->
<fileSeparator>/</fileSeparator>
<!-- 包含的依赖范围:compile + runtime(不包含 test) -->
<includeScope>runtime</includeScope>
<!-- 是否去掉版本号(false 保留完整路径) -->
<stripVersion>false</stripVersion>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
package org.yourcompany.yourproject;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import cn.hutool.core.util.StrUtil;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
public CommandLineRunner run() {
return args -> {
System.out.print(StrUtil.upperFirst("hello"));
System.out.println("Hello! This is a Spring Boot CLI app.");
};
}
}
package org.yourcompany.yourproject;
/**
* CoinData 抛硬币数据类
*/
public class CoinData {
public int counter;
public int head;
public int aggHeadCount;
public double aggHeadProb;
@Override
public String toString() {
return "counter:" + String.valueOf(counter) + ", head:" + String.valueOf(head) + ", aggHeadCount:" + String.valueOf(aggHeadCount) + ", aggHeadProb:" + String.valueOf(aggHeadProb);
}
}
{
"nbformat": 4,
"nbformat_minor": 5,
"metadata": {
"language_info": {
"name": "java"
}
},
"cells": [
{
"id": "a752b509-2da5-4efc-84c0-6224ba317a0c",
"cell_type": "code",
"source": "import java.io.File;\r\nimport java.nio.file.Paths;\r\n\r\n\r\n// 打印当前真实的工作目录\r\nSystem.out.println(\"Current Working Directory: \" + Paths.get(\".\").toAbsolutePath());\r\nSystem.out.println(\"Current Working Directory: \" + new File(\".\").getAbsoluteFile());\r\n// 打印当前可访问到的classpath\r\nSystem.out.println(\"classpath: \" + System.getProperty(\"java.class.path\"));",
"metadata": {
"language": "java"
},
"execution_count": null,
"outputs": []
},
{
"id": "3fd13d2a-7727-4cc2-8168-e8953f4f0fef",
"cell_type": "markdown",
"source": "## 定义一个 CoinData 类\r\n\r\n包含如下信息:\r\n- counter: 哪一次抛硬币,\r\n- head: 是否是正面,\r\n- aggHeadCount: 从第一次开始累积正面次数,\r\n- aggHeadProb: 累积正面的概率",
"metadata": {
"language": "markdown",
"id": "3fd13d2a-7727-4cc2-8168-e8953f4f0fef"
}
},
{
"id": "e1d05a28-286f-4ec9-a5d3-d369e2d51d95",
"cell_type": "code",
"source": "\r\n/**\r\n * CoinData2 抛硬币数据类\r\n*/\r\nclass CoinData2{\r\n public int counter;\r\n public int head;\r\n public int aggHeadCount;\r\n public double aggHeadProb;\r\n\r\n public String toString(){\r\n List<String> lst = new ArrayList<>();\r\n lst.add(\"a\");\r\n lst.stream().filter(e -> e.equals(\"a\")).toList();\r\n return \"counter:\"+String.valueOf(counter) +\", head:\"+ String.valueOf(head)+\", aggHeadCount:\" +String.valueOf(aggHeadCount) +\", aggHeadProb:\"+ String.valueOf(aggHeadProb) ;\r\n }\r\n\r\n}",
"metadata": {
"language": "java"
},
"execution_count": null,
"outputs": []
},
{
"id": "905bfbc8-dde1-4cfd-b76e-bc0acf45dba1",
"cell_type": "code",
"source": "import java.util.Random;\r\nimport org.yourcompany.yourproject.CoinData; //可以从当前项目中引入 CoinData 类, 该类的定义同 CoinData2。\r\n\r\nRandom random=new Random();\r\nint count=100; //抛硬币次数\r\n\r\nList<CoinData> coinList=new ArrayList<>();\r\n\r\n//随机完成指定次数的抛硬币动作\r\nfor(int i=1;i<=count;i++){\r\n CoinData coin=new CoinData();\r\n coin.counter=i;\r\n coin.head=random.nextInt(2); //0 or 1\r\n coin.aggHeadProb=0 ;\r\n coin.aggHeadCount=0;\r\n coinList.add(coin);\r\n}\r\n\r\n//计算概率\r\n for(int i=1;i<=count;i++){\r\n CoinData coin=coinList.get(i-1);\r\n CoinData previousCoin=null;\r\n if (i==1){\r\n previousCoin=new CoinData();\r\n previousCoin.counter=0;\r\n previousCoin.head=0;\r\n previousCoin.aggHeadProb=0 ;\r\n previousCoin.aggHeadCount=0;\r\n }else{\r\n previousCoin=coinList.get(i-2);\r\n }\r\n\r\n if (coin.head==1){\r\n coin.aggHeadCount=previousCoin.aggHeadCount+1;}\r\n else{\r\n coin.aggHeadCount=previousCoin.aggHeadCount;\r\n }\r\n\r\n coin.aggHeadProb=(coin.aggHeadCount+0.0)/i;\r\n System.out.println(coin);\r\n}",
"metadata": {
"language": "java"
},
"execution_count": null,
"outputs": []
},
{
"id": "6046233b-9f32-4229-8ff5-0cb0288645bb",
"cell_type": "code",
"source": "import tech.tablesaw.api.IntColumn;\r\nimport tech.tablesaw.api.DoubleColumn;\r\nimport tech.tablesaw.api.Table;\r\nimport tech.tablesaw.plotly.Plot;\r\nimport tech.tablesaw.plotly.api.LinePlot;\r\nimport tech.tablesaw.plotly.components.Figure;\r\nimport tech.tablesaw.plotly.components.Layout;\r\nimport tech.tablesaw.plotly.traces.ScatterTrace;\r\n\r\n// 1. Create a Tablesaw Table and add columns\r\nTable table = Table.create(\"Monte Carlo Coin Toss Convergence\");\r\nIntColumn counterCol = IntColumn.create(\"Trial\");\r\nDoubleColumn probCol = DoubleColumn.create(\"Aggregated Probability\");\r\n\r\n// 2. Populate the table from your coinList\r\nfor (CoinData coin : coinList) {\r\n counterCol.append(coin.counter);\r\n probCol.append(coin.aggHeadProb);\r\n}\r\ntable.addColumns(counterCol, probCol);",
"metadata": {
"language": "java"
},
"execution_count": null,
"outputs": []
},
{
"id": "7cd4d0f3-92f2-4969-9f44-d719a441d64c",
"cell_type": "markdown",
"source": "",
"metadata": {
"language": "markdown",
"id": "7cd4d0f3-92f2-4969-9f44-d719a441d64c"
}
},
{
"id": "f2fc1809-3f8f-4d56-aaed-6558fbc626d1",
"cell_type": "code",
"source": "// 3. Create a trend plot (Probability vs. Trial Number)\r\n// LinePlot is the simplest way to show the trend line\r\nFigure figure = LinePlot.create(\r\n \"Probability Convergence to 0.5\",\r\n table,\r\n \"Trial\",\r\n \"Aggregated Probability\"\r\n);\r\n\r\n\r\n",
"metadata": {
"language": "java"
},
"execution_count": null,
"outputs": []
},
{
"id": "bc758e1c-5500-4fef-9dfb-ac271e13134e",
"cell_type": "code",
"source": "// 4. Display the plot\r\nimport java.io.File;\r\nimport java.nio.file.Paths;\r\n\r\n// 1. 打印当前真实的工作目录,确认文件到底去哪了\r\nSystem.out.println(\"Current Working Directory: \" + new File(\".\").getAbsolutePath());\r\n\r\n// 2. 强制使用绝对路径生成 HTML\r\n// 请将下面的路径修改为你电脑上存在的某个确定目录,例如 \"D:/test/coin_plot.html\" 或 \"/Users/name/Desktop/plot.html\"\r\nString absolutePath = Paths.get(\".\").toAbsolutePath().normalize().toString() + File.separator + \"coin_convergence.html\";\r\nSystem.out.println(\"Target file path: \" + absolutePath);\r\n\r\n// 3. 使用指定路径保存, 并使用浏览器打开输出的html图像文件\r\nPlot.show(figure, new File(absolutePath));",
"metadata": {
"language": "java"
},
"execution_count": null,
"outputs": []
}
]
}

https://github.com/jtablesaw/tablesaw
https://jtablesaw.github.io/tablesaw/
https://dflib.org/
https://jmetal.readthedocs.io/
https://haifengl.github.io/overview.html
https://tribuo.org/learn/4.3/docs/
https://tribuo.org/learn/4.3/tutorials/irises-tribuo-v4.html
https://github.com/jupyter-java
https://github.com/jupyter-java/awesome-jupyter-java
https://www.javaspring.net/blog/java-jupyter-notebook/
https://www.javathinking.com/blog/using-jupyter-notebook-for-java/
https://www.javaspring.net/blog/java-jupyter-notebook/
https://readmedium.com/java-jupyter-plotly-e1bbaa7f2be8
https://github.com/jtablesaw/tablesaw/tree/master/jsplot/src/test/java/tech/tablesaw/examples
https://medium.com/oracledevs/machine-learning-in-java-with-the-tribuo-library-and-oracle-ai-database-26ai-unleashing-jupyter-ef4af5d8c5a4
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。